### Run Formlander with Docker (Quick Start) Source: https://formlander.com/docs/deployment This is a quick start command to run Formlander using Docker. It maps the host port 8080 to the container port 8080, sets a random session secret, and mounts a local storage directory into the container. The latest Formlander image is used. ```shell docker run -d \ -p 8080:8080 \ -e FORMLANDER_SESSION_SECRET=$(openssl rand -hex 32) \ -v $(pwd)/storage:/app/storage \ karloscodes/formlander:latest ``` -------------------------------- ### React Example for Cloudflare Turnstile Integration Source: https://formlander.com/docs/bot-protection This React component demonstrates how to integrate Cloudflare Turnstile into a single-page application. It uses the `@marsidev/react-turnstile` component, manages the token state, and appends it to the form data before submission. ```javascript import { Turnstile } from '@marsidev/react-turnstile' function ContactForm() { const [token, setToken] = useState('') const handleSubmit = async (e) => { e.preventDefault() const formData = new FormData(e.target) formData.append('cf-turnstile-response', token) const response = await fetch('https://your-domain.com/forms/contact/submit?token=YOUR_TOKEN', { method: 'POST', body: formData, }) // Handle response... } return (
``` ```javascript const form = document.getElementById('contact-form'); const status = document.getElementById('form-status'); form.addEventListener('submit', async (e) => { e.preventDefault(); // Show loading state status.textContent = 'Sending...'; status.className = 'loading'; // Get form data const formData = new FormData(form); try { const response = await fetch('https://your-domain.com/forms/contact/submit?token=YOUR_FORM_TOKEN', { method: 'POST', body: formData }); const result = await response.json(); if (result.ok) { status.textContent = 'Message sent successfully!'; status.className = 'success'; form.reset(); } else { status.textContent = 'Error: ' + result.error; status.className = 'error'; } } catch (error) { status.textContent = 'Failed to send message. Please try again.'; status.className = 'error'; } }); ``` -------------------------------- ### HTML Form Example with Token Source: https://formlander.com/docs/security This HTML snippet demonstrates how a legitimate form is embedded with a Formlander public token in its action URL. This is a basic setup and requires additional security measures. ```html
``` -------------------------------- ### Rate Limit Log Entry Example Source: https://formlander.com/docs/abuse-prevention This JSON object represents a log entry for a submission that was blocked due to exceeding the rate limit. It includes the log level, timestamp, a message indicating the block, the form slug, the hashed IP address, and the reason for the block. ```json { "level": "warn", "ts": "2025-11-07T14:30:00Z", "msg": "submission blocked: rate limit exceeded", "form_slug": "contact", "ip_hash": "abc123...", "reason": "rate_limit" } ``` -------------------------------- ### HTML Form Submission Example Source: https://formlander.com/docs/overview This snippet demonstrates how to create an HTML form that can be submitted to a Formlander endpoint. The 'action' attribute specifies the Formlander API endpoint including the form's slug and secret token. All form fields are captured and stored as JSON. ```html
``` -------------------------------- ### Deploy Formlander with Cloudflare Tunnel Source: https://formlander.com/docs/deployment Set up Formlander for production using Cloudflare Tunnel, which provides automatic HTTPS and DDoS protection. This involves installing `cloudflared`, authenticating, creating a tunnel, configuring ingress rules, and routing DNS. ```bash # Install cloudflared curl -L https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 -o cloudflared chmod +x cloudflared && sudo mv cloudflared /usr/local/bin/ # Authenticate and create tunnel cloudflared tunnel login cloudflared tunnel create formlander # Configure tunnel (~/.cloudflared/config.yml) tunnel: credentials-file: /root/.cloudflared/.json ingress: - hostname: forms.yourdomain.com service: http://localhost:8080 - service: http_status:404 # Route DNS and start cloudflared tunnel route dns formlander forms.yourdomain.com cloudflared service install sudo systemctl start cloudflared ``` -------------------------------- ### Example Blocked Submission Log Entry Source: https://formlander.com/docs/security Formlander logs blocked submissions, including reasons like honeypot triggers or failed Turnstile validation. Monitoring these logs helps identify spam patterns and potential attacks. ```json { "level": "warn", "ts": "2025-11-05T19:30:00Z", "msg": "submission blocked: honeypot triggered", "form_slug": "contact", "ip_hash": "abc123...", "reason": "honeypot" } ``` -------------------------------- ### React Fetch API Form Submission Source: https://formlander.com/docs/integration Integrate Formlander submissions within a React application using the Fetch API. This example demonstrates managing form state with useState and appending form data for submission. It allows for dynamic form handling and custom response messages. ```javascript const [formData, setFormData] = useState({ name: '', email: '', message: '' }); const handleSubmit = async (e) => { e.preventDefault(); const body = new FormData(); Object.keys(formData).forEach(k => body.append(k, formData[k])); const res = await fetch('https://your-domain.com/forms/contact/submit?token=YOUR_TOKEN', { method: 'POST', body }); const result = await res.json(); if (result.ok) alert('Sent!'); }; ``` -------------------------------- ### Run Formlander Binary with a .env File Source: https://formlander.com/docs/deployment Configure and run the Formlander binary by creating a `.env` file in the current directory. This file specifies production settings, port, session secret, and data directory. The binary automatically loads this configuration. ```dotenv FORMLANDER_ENV=production FORMLANDER_PORT=8080 FORMLANDER_SESSION_SECRET=your-secret-here FORMLANDER_DATA_DIR=./storage ``` ```bash ./formlander ``` -------------------------------- ### Run Formlander with Docker and .env File Source: https://formlander.com/docs/deployment This command demonstrates how to run Formlander with Docker using an existing `.env` file for configuration. It uses the `--env-file` flag to load variables from the `.env` file, maps ports, and mounts the storage directory. ```shell docker run -d \ --env-file .env \ -p 8080:8080 \ -v $(pwd)/storage:/app/storage \ karloscodes/formlander:latest ``` -------------------------------- ### Run Formlander Binary with Environment Variables Source: https://formlander.com/docs/deployment Execute the Formlander binary after setting necessary environment variables for session secret and data directory. This method is suitable for quick local testing or environments where environment variables are managed externally. ```bash export FORMLANDER_SESSION_SECRET=$(openssl rand -hex 32) export FORMLANDER_DATA_DIR=./storage ./formlander ``` -------------------------------- ### Configure Submission Rate Limiting via Environment Variables Source: https://formlander.com/docs/security Alternatively, configure submission rate limits per hour per IP address using environment variables for flexibility in deployment. ```env FORMLANDER_SUBMISSION_RATE_PER_HOUR=120 ``` -------------------------------- ### Configure Formlander with a .env File Source: https://formlander.com/docs/deployment This snippet shows how to create and use a `.env` file for local development configuration of Formlander. It includes settings for the session secret, environment, port, log level, and data directory. Environment variables will override values set in the `.env` file. ```shell # Required in production FORMLANDER_SESSION_SECRET=your-secret-here # Optional overrides FORMLANDER_ENV=production FORMLANDER_PORT=8080 FORMLANDER_LOG_LEVEL=info FORMLANDER_DATA_DIR=./storage ``` -------------------------------- ### Testing Origin Allowlisting with cURL Source: https://formlander.com/docs/abuse-prevention This command demonstrates how to test origin allowlisting using `curl`. It shows how to send a POST request to a Formlander endpoint, including the necessary form token and specifying the 'Origin' header to simulate a request from a specific domain. ```bash curl -X POST https://your-domain.com/forms/contact/submit?token=abc123 \ -H "Origin: https://example.com" \ -d "name=John Doe&email=john@example.com&message=Hello" ``` -------------------------------- ### Configure Caddy as a Reverse Proxy for Formlander Source: https://formlander.com/docs/deployment Use Caddy as a reverse proxy for Formlander, simplifying HTTPS configuration through automatic Let's Encrypt certificate management. This configuration forwards requests to the local Formlander instance. ```caddy forms.yourdomain.com { reverse_proxy localhost:8080 } ``` -------------------------------- ### Run Formlander with Docker, Mixing .env and Environment Variables Source: https://formlander.com/docs/deployment This Docker command shows how to run Formlander while mixing configuration from both an `.env` file and direct environment variables. Direct environment variables, like `FORMLANDER_SESSION_SECRET`, will override settings present in the `.env` file. ```shell docker run -d \ -e FORMLANDER_SESSION_SECRET=$(openssl rand -hex 32) \ --env-file .env \ -p 8080:8080 \ -v $(pwd)/storage:/app/storage \ karloscodes/formlander:latest ``` -------------------------------- ### Common Formlander Configuration Options Source: https://formlander.com/docs/deployment This snippet lists common environment variables used to configure Formlander. These include settings for the application environment, HTTP port, session secret, log level, and data directory. ```shell FORMLANDER_ENV=production # Environment: development, production (default: development) FORMLANDER_PORT=8080 # HTTP port (default: 8080) FORMLANDER_SESSION_SECRET=your-secret # HMAC secret (REQUIRED in production) FORMLANDER_LOG_LEVEL=info # Log level: debug, info, warn, error (default: info) FORMLANDER_DATA_DIR=./storage # Data directory (default: ./storage) ``` -------------------------------- ### Pull Formlander Docker Images for Specific Architectures Source: https://formlander.com/docs/deployment Manually pull Docker images for Formlander tailored to specific CPU architectures (amd64 and arm64). Note that multi-arch tags like 'latest' or version without suffix will automatically select the correct image for your system. ```bash docker pull karloscodes/formlander:v1.0.0-amd64 docker pull karloscodes/formlander:v1.0.0-arm64 ``` -------------------------------- ### Docker Image Pull Commands Source: https://formlander.com/docs/deployment This snippet provides commands for pulling Formlander Docker images. It includes pulling the latest multi-arch image, architecture-specific latest tags (amd64, arm64), and specific version tags. ```shell # Latest stable release (multi-arch manifest) docker pull karloscodes/formlander:latest # Architecture-specific latest tags docker pull karloscodes/formlander:latest-amd64 docker pull karloscodes/formlander:latest-arm64 # Specific version (multi-arch manifest) docker pull karloscodes/formlander:v1.0.0 ``` -------------------------------- ### JavaScript (Fetch) Integration Source: https://formlander.com/docs/integration Submit forms asynchronously using JavaScript's `fetch` API for a controlled user experience without page reloads. ```APIDOC ## POST /forms/{form_slug}/submit (JavaScript Fetch) ### Description Submits form data asynchronously using the Fetch API. Allows for custom handling of responses and user feedback. ### Method POST ### Endpoint `https://your-domain.com/forms/contact/submit?token=YOUR_TOKEN` ### Parameters #### Query Parameters - **token** (string) - Required - Your Formlander form submission token. #### Request Body Form data is sent as `FormData`. ### Request Example ```javascript const form = document.getElementById('contact-form'); form.addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(form); const response = await fetch('https://your-domain.com/forms/contact/submit?token=YOUR_TOKEN', { method: 'POST', body: formData }); const result = await response.json(); if (result.ok) { alert('Message sent!'); form.reset(); } }); ``` ### Response #### Success Response (200) A JSON object indicating the submission status. #### Response Example ```json { "ok": true } ``` ``` -------------------------------- ### Configure Submission Rate Limiting Source: https://formlander.com/docs/security Set submission rate limits per hour per IP address to prevent spam floods. This can be configured using a YAML config file or environment variables. ```yaml submissionrateperhour: 120 # Max submissions per hour per IP ``` ```yaml # Contact forms: More restrictive submissionrateperhour: 10 # Newsletter signups: Very restrictive submissionrateperhour: 5 # Feedback forms: More lenient submissionrateperhour: 60 ``` -------------------------------- ### HTML Form Integration Source: https://formlander.com/docs/integration The simplest way to integrate Formlander is by using traditional HTML forms. Point your form's `action` attribute to your Formlander endpoint. ```APIDOC ## POST /forms/{form_slug}/submit ### Description Submits form data via a traditional HTML form. ### Method POST ### Endpoint `https://your-domain.com/forms/contact/submit?token=YOUR_FORM_TOKEN` ### Parameters #### Query Parameters - **token** (string) - Required - Your Formlander form submission token. #### Request Body Form data is sent as `multipart/form-data`. ### Request Example ```html
``` ### Response #### Success Response (200) Typically a redirect to a success page or a JSON response indicating success. #### Response Example (Redirect or JSON indicating success) ``` ```APIDOC ## HTML Forms with Custom Redirects ### Description Control user redirection after form submission by adding hidden fields for success and error URLs. ### Method POST ### Endpoint `https://your-domain.com/forms/contact/submit?token=YOUR_FORM_TOKEN` ### Parameters #### Query Parameters - **token** (string) - Required - Your Formlander form submission token. #### Request Body Form data including `_success_url` and `_error_url` hidden fields. - **_success_url** (string) - Optional - URL to redirect to upon successful submission. - **_error_url** (string) - Optional - URL to redirect to upon submission failure. ### Request Example ```html
``` ``` -------------------------------- ### Origin Allowlisting Configuration Source: https://formlander.com/docs/abuse-prevention Configure allowed domains to prevent form token copying and cross-site abuse. Submissions are only accepted from specified origins. ```APIDOC ## Origin Allowlisting ### Description Specify trusted domains from which form submissions will be accepted. This prevents attackers from embedding your form on their malicious websites using your form token. ### Method Not applicable (Configuration via UI) ### Endpoint Not applicable (Configuration via UI) ### Parameters #### Request Body - **Allowed Origins** (string) - Optional - Comma-separated list of domains and subdomains (e.g., `example.com, *.example.com`). Leave empty to allow all origins (not recommended for production). ### Request Example **UI Configuration Example:** `example.com, www.example.com, *.example.com` ### Response #### Success Response (200) Form submission processed successfully. #### Error Response (403 Forbidden) ```json { "ok": false, "error": "origin not allowed" } ``` ``` -------------------------------- ### Formlander Request Flow Diagram Source: https://formlander.com/docs/overview This diagram illustrates the request flow for Formlander. It shows how an HTML form submission is processed by the Formlander API, stored in SQLite, and then dispatched asynchronously via webhooks or Mailgun email forwarding. It also indicates access through the dashboard and exports. ```mermaid graph LR A[HTML form] --> B(Formlander API) B --> C{SQLite (submissions)} B --> D[Webhook dispatcher (async, retry)] B --> E[Mailgun email forwarding] B --> F[Dashboard & exports] ``` -------------------------------- ### Environment Variables for Rate Limiting Source: https://formlander.com/docs/security These environment variables are for configuring global rate limiting defaults in Formlander. Note that per-form configuration is currently managed via the admin dashboard. ```env # Global defaults (if supported in your version) FORMLANDER_RATE_MAX_REQUESTS=60 # Max requests per window FORMLANDER_RATE_WINDOW_SECONDS=60 # Time window in seconds ``` -------------------------------- ### Form Submission API Source: https://formlander.com/docs/overview This section details the API endpoints for submitting form data to Formlander. ```APIDOC ## POST /forms/{slug}/submit ### Description Accepts form submissions via standard HTML form POST requests. The slug and token are provided in the URL. ### Method POST ### Endpoint `/forms/{slug}/submit?token={secret}` ### Parameters #### Path Parameters - **slug** (string) - Required - The unique identifier for the form. - **secret** (string) - Required - The secret token associated with the form for authentication. #### Query Parameters None #### Request Body - **field_name** (string) - Optional - Any field from your HTML form. ### Request Example ```html
``` ### Response #### Success Response (200) This endpoint typically returns a redirect or a simple success message upon successful submission. Specific response details are not provided in the source, but it implies successful processing. #### Response Example (No specific example provided, but implies a successful form processing.) ``` ```APIDOC ## POST /x/api/v1/submissions ### Description Accepts form submissions in JSON format. The form slug and token are included in the request body. ### Method POST ### Endpoint `/x/api/v1/submissions` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **slug** (string) - Required - The unique identifier for the form. - **token** (string) - Required - The secret token associated with the form for authentication. - **data** (object) - Required - An object containing the form field data. - **field_name** (any) - Optional - Key-value pairs representing the form fields and their values. ### Request Example ```json { "slug": "contact", "token": "abc123", "data": { "name": "John Doe", "email": "john.doe@example.com", "message": "This is a test message." } } ``` ### Response #### Success Response (200) This endpoint typically returns a success status upon successful submission of the JSON payload. Specific response details are not provided in the source, but it implies successful processing. #### Response Example (No specific example provided, but implies a successful JSON submission processing.) ``` -------------------------------- ### Submit Form via JSON API Source: https://formlander.com/docs/integration This endpoint allows for programmatic submission of form data, suitable for headless or API-first integrations. It requires the form slug, a security token, and the data payload. ```APIDOC ## POST /x/api/v1/submissions ### Description Submits form data to Formlander for processing. This is the primary endpoint for API-first integrations. ### Method POST ### Endpoint /x/api/v1/submissions ### Parameters #### Request Body - **form_slug** (string) - Required - The unique identifier for the form. - **token** (string) - Required - A security token for the form. - **data** (object) - Required - The form data to be submitted. Keys should match the form field names. ### Request Example ```json { "form_slug": "contact", "token": "YOUR_FORM_TOKEN", "data": { "name": "John Doe", "email": "john@example.com", "message": "Hello world" } } ``` ### Response #### Success Response (200) - **ok** (boolean) - Indicates if the submission was successful. - **submission_id** (integer) - The unique ID of the submitted entry. - **received_at** (string) - ISO 8601 timestamp of when the submission was received. #### Response Example ```json { "ok": true, "submission_id": 123, "received_at": "2025-11-07T10:30:00Z" } ``` #### Error Response (400/429/500) - **ok** (boolean) - Indicates that the submission failed. - **error** (string) - A message describing the error. #### Error Response Example ```json { "ok": false, "error": "rate limit exceeded" } ``` ``` -------------------------------- ### Include Formlander JavaScript SDK (HTML) Source: https://formlander.com/docs/integration This HTML script tag demonstrates how to include the Formlander JavaScript SDK in your project. Adding this script to your pages automatically enhances any detected Formlander forms with features like automatic retry logic and improved error handling, without requiring further JavaScript code. ```html ``` -------------------------------- ### HTML Form with Cloudflare Turnstile Integration Source: https://formlander.com/docs/abuse-prevention This HTML snippet demonstrates a basic contact form structure. It includes placeholders for form fields, a submit button, and integration with Cloudflare's Turnstile captcha service. The script to load the Turnstile API is also included. ```html
``` -------------------------------- ### Submit Form with React and Fetch API Source: https://formlander.com/docs/integration This React component implements a contact form with state management for form inputs and submission status. It uses the Fetch API to send form data asynchronously and updates the UI to reflect the submission status (loading, success, or error). ```javascript import { useState } from 'react'; export default function ContactForm() { const [formData, setFormData] = useState({ name: '', email: '', message: '' }); const [status, setStatus] = useState({ type: '', message: '' }); const [loading, setLoading] = useState(false); const handleChange = (e) => { setFormData({ ...formData, [e.target.name]: e.target.value }); }; const handleSubmit = async (e) => { e.preventDefault(); setLoading(true); setStatus({ type: '', message: '' }); const formBody = new FormData(); Object.keys(formData).forEach(key => { formBody.append(key, formData[key]); }); try { const response = await fetch( 'https://your-domain.com/forms/contact/submit?token=YOUR_FORM_TOKEN', { method: 'POST', body: formBody } ); const result = await response.json(); if (result.ok) { setStatus({ type: 'success', message: 'Message sent successfully!' }); setFormData({ name: '', email: '', message: '' }); } else { setStatus({ type: 'error', message: result.error || 'Failed to send message' }); } } catch (error) { setStatus({ type: 'error', message: 'Network error. Please try again.' }); } finally { setLoading(false); } }; return (
``` -------------------------------- ### JavaScript Fetch API Form Submission Source: https://formlander.com/docs/integration Submit forms asynchronously using the Fetch API in JavaScript. This method prevents page reloads and allows for custom feedback, such as success alerts and form resetting. It requires client-side JavaScript to handle the submission logic. ```javascript const form = document.getElementById('contact-form'); form.addEventListener('submit', async (e) => { e.preventDefault(); const formData = new FormData(form); const response = await fetch('https://your-domain.com/forms/contact/submit?token=YOUR_TOKEN', { method: 'POST', body: formData }); const result = await response.json(); if (result.ok) { alert('Message sent!'); form.reset(); } }); ``` -------------------------------- ### Configure Nginx as a Reverse Proxy for Formlander Source: https://formlander.com/docs/deployment Set up Nginx to act as a reverse proxy for Formlander, enabling HTTPS and forwarding requests to the Formlander instance running on localhost:8080. This requires configuring SSL certificates and proxy headers. ```nginx server { listen 443 ssl http2; server_name forms.yourdomain.com; ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } } ``` -------------------------------- ### Form Submission Response Formats (JSON) Source: https://formlander.com/docs/integration Form submissions processed by Formlander return JSON objects. Successful submissions include an 'ok' field set to true, along with a 'submission_id' and 'received_at' timestamp. Error responses indicate failure with 'ok' set to false and an 'error' message detailing the issue, such as rate limiting or validation problems. ```json { "ok": true, "submission_id": 123, "received_at": "2025-11-07T10:30:00Z" } ``` ```json { "ok": false, "error": "rate limit exceeded" } ``` -------------------------------- ### Submit Form Data via JSON API (JavaScript) Source: https://formlander.com/docs/integration This asynchronous JavaScript function allows for submitting form data to the Formlander JSON API. It requires the form's slug, an authentication token, and the form data as input. The function makes a POST request to the submissions endpoint and returns the parsed JSON response. It's crucial to handle potential errors and display appropriate feedback to the user. This method is ideal for headless or API-first integrations. ```javascript async function submitForm(formSlug, token, data) { const response = await fetch('https://your-domain.com/x/api/v1/submissions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ form_slug: formSlug, token: token, data: data }) }); return response.json(); } // Usage const result = await submitForm('contact', 'YOUR_FORM_TOKEN', { name: 'John Doe', email: 'john@example.com', message: 'Hello world' }); if (result.ok) { console.log('Submitted:', result.submission_id); } ``` -------------------------------- ### Submit Form Data via cURL (Successful Origin) Source: https://formlander.com/docs/abuse-prevention This cURL command demonstrates a successful submission of form data to the Formlander endpoint. It includes setting the correct Origin header, Content-Type, and the payload. Ensure the token and domain are replaced with your actual values. ```shell curl -X POST \ -H "Origin: https://example.com" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "name=Test&email=test@example.com" \ "https://your-domain.com/forms/contact/submit?token=abc123" ``` -------------------------------- ### HTML Form Submission with Custom Redirects Source: https://formlander.com/docs/integration Enhance HTML form integration by adding hidden input fields for custom success and error URLs. This allows control over post-submission navigation without requiring JavaScript, though JavaScript/AJAX submissions need manual redirect handling. ```html
``` -------------------------------- ### HTML Form Submission with Formlander Source: https://formlander.com/docs/integration Integrate Formlander using a standard HTML form. The form's 'action' attribute should point to your Formlander endpoint. This method is simple and reliable, but involves a page redirect after submission and has limited error handling. ```html
``` -------------------------------- ### JSON API Integration Source: https://formlander.com/docs/integration Submit form data directly via JSON to the Formlander API endpoint, suitable for server-side integrations or custom API clients. ```APIDOC ## POST /x/api/v1/submissions ### Description Submits form data as a JSON payload to the Formlander API. This endpoint is ideal for server-to-server communication or when sending structured data. ### Method POST ### Endpoint `https://your-domain.com/x/api/v1/submissions` ### Parameters #### Headers - **Content-Type**: `application/json` #### Request Body - **form_slug** (string) - Required - The slug of the form to submit to. - **token** (string) - Required - Your Formlander form submission token. - **data** (object) - Required - An object containing the form field data. - **fieldName** (any) - The value for the corresponding form field. ### Request Example ```javascript await fetch('https://your-domain.com/x/api/v1/submissions', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ form_slug: 'contact', token: 'YOUR_TOKEN', data: { name: 'John', email: 'john@example.com', message: 'Hi' } }) }); ``` ### Response #### Success Response (200) A JSON response confirming the submission. #### Response Example ```json { "message": "Submission received successfully." } ``` ``` -------------------------------- ### Monitor Bot Protection Log Entry Source: https://formlander.com/docs/bot-protection This log entry captures a failed captcha validation attempt, indicating a potential bot submission that was blocked by Formlander. It includes details like the timestamp, message, form slug, and the reason for blocking. ```json { "level": "warn", "ts": "2025-11-07T14:30:00Z", "msg": "submission blocked: captcha validation failed", "form_slug": "contact", "ip_hash": "abc123...", "reason": "captcha_failed" } ``` -------------------------------- ### JSON Response for Rate Limit Exceeded Source: https://formlander.com/docs/security This JSON response is returned when a client exceeds the configured rate limit for submissions to a form. It indicates that the request was denied due to too many requests. ```json { "ok": false, "error": "rate limit exceeded" } ``` -------------------------------- ### Submit Form Data via cURL (Failed Origin) Source: https://formlander.com/docs/abuse-prevention This cURL command illustrates a failed submission due to an incorrect Origin header. Formlander is configured to reject requests from unauthorized origins, returning a 403 Forbidden error. This is a security measure to prevent cross-site request forgery. ```shell curl -X POST \ -H "Origin: https://attacker.com" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "name=Test&email=test@example.com" \ "https://your-domain.com/forms/contact/submit?token=abc123" ```