Documentation

Everything you need to add form handling to your static site.

Quick Start

Get up and running in 3 steps:

  1. Sign up and create a project with a form endpoint.
  2. Copy your form endpoint URL from the dashboard.
  3. Add the HTML below to your site — that's it.
HTML
<!-- Include the StatikForm script for spam protection -->
<script src="https://statikform.pages.dev/statikform.js"></script>

<form action="https://statikform.pages.dev/api/f/YOUR_FORM_ID" method="POST">
  <input type="email" name="email" required />
  <textarea name="message"></textarea>

  <!-- Honeypot: hide this with CSS -->
  <input type="text" name="_gotcha"
         style="display:none" tabindex="-1" />

  <button type="submit">Send</button>
</form>

Replace YOUR_FORM_ID with your actual form endpoint ID from the dashboard.

HTML Form Submission

The simplest integration. Set your form's action to your StatikForm endpoint and use method="POST". All named form fields are captured as submission data.

HTML
<form action="https://statikform.pages.dev/api/f/YOUR_FORM_ID" method="POST">
  <input type="text" name="name" />
  <input type="email" name="email" />
  <input type="tel" name="phone" />
  <textarea name="message"></textarea>
  <select name="subject">
    <option>General</option>
    <option>Support</option>
    <option>Sales</option>
  </select>
  <button type="submit">Send</button>
</form>

After submission, the user is redirected to a default thank-you page. You can customize this with a custom redirect URL.

JavaScript / Fetch

For single-page apps or AJAX forms, send a JSON POST request. The endpoint returns JSON and supports CORS from any origin (or only your allowed domains).

JavaScript
const ENDPOINT = 'https://statikform.pages.dev/api/f/YOUR_FORM_ID';

// Step 1: Fetch a time token
const { token } = await fetch(ENDPOINT).then(r => r.json());

// Step 2: Submit with the token
const res = await fetch(ENDPOINT, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    email: 'user@example.com',
    message: 'Hello!',
    _t: token,      // time token (required)
    _gotcha: ''     // honeypot (leave empty)
  })
});

const data = await res.json();
// { success: true }

Important: When using fetch, you must manually request a time token via GET /api/f/YOUR_FORM_ID and include it as _t in your payload. The statikform.js script handles this automatically for HTML forms.

Spam Protection

Every form endpoint has multiple layers of built-in spam and abuse protection enabled by default. This includes rate limiting, bot detection, token verification, and optional domain restrictions. No configuration required — just include the StatikForm script and honeypot field for maximum protection.

Time-Based Tokens

Time tokens verify that a real user loaded your page before submitting. Submissions without a valid token are rejected.

Automatic (recommended)

Include the StatikForm script on your page. It automatically fetches a token and injects it into your form.

HTML
<script src="https://statikform.pages.dev/statikform.js"></script>

Add this once per page. It handles all StatikForm forms on the page.

Manual (for JavaScript/fetch)

If you're submitting via JavaScript, fetch the token yourself:

Request
GET /api/f/YOUR_FORM_ID

Response: { "token": "abc123.def456" }

Include the token as _t in your submission data (form field or JSON body).

Tokens that are too new, too old, or have an invalid signature will be rejected.

Honeypot Fields

Add a hidden field named _gotcha to your form. This field acts as a trap for automated spam and should be hidden from real users.

HTML
<!-- Hide with inline style or CSS class -->
<input type="text" name="_gotcha"
       style="display:none" tabindex="-1"
       autocomplete="off" />

Tip: Use style="display:none" or a CSS class to hide the field rather than type="hidden".

Domain Allowlisting

Restrict which websites can submit to your form. Configure allowed domains in your form settings in the dashboard. Submissions from other domains are rejected with a 403 error.

Example

Setting allowed domains to example.com, mysite.org will:

  • Accept from example.com
  • Accept from sub.example.com
  • Accept from mysite.org
  • Reject from evil.com

Leave the field empty to accept submissions from any domain. Domain matching includes subdomains.

Custom Redirects

By default, HTML form submissions redirect to a StatikForm thank-you page. You can set a custom redirect URL in your form settings to send users back to your own site.

Example

Set the redirect URL in your form settings to:

https://yoursite.com/thank-you

After a successful submission, the user will be redirected there instead of the default page.

Note: Custom redirects only apply to HTML form submissions (method="POST"). JSON/fetch submissions receive a JSON response instead.

CSV Export

Export all submissions for a form as a CSV file. Click the "Export CSV" button on any form page in the dashboard. The CSV includes all fields from all submissions, with columns auto-detected from the data.

Rate Limits

Each form endpoint is rate-limited per IP address to prevent abuse. This is always enabled and cannot be disabled. Exceeding the limit returns a 429 status code.

Rate-limited response
HTTP 429
{ "error": "Too many submissions. Please try again later." }

CORS

All form endpoints support CORS, so you can submit from JavaScript on any domain. The endpoint responds to OPTIONS preflight requests and sets appropriate Access-Control-Allow-* headers.

Response headers
Access-Control-Allow-Origin: <request origin>
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type

If you've configured domain allowlisting, only those domains will receive successful responses — but CORS headers are still sent so the browser can read the error.