# CatchForm — full documentation Source: https://catchform.dev. Generated from the pages themselves, so it never disagrees with the site. ## Documentation https://catchform.dev/docs API Documentation Technical reference for integrating CatchForm with your forms. Everything you need to know about endpoints, parameters, and responses. ← Back to home Endpoint All form submissions are sent to a single endpoint: POST https://catchform.dev/f/{token} Replace {token} with your form's unique token, shown in the dashboard after creating a form. Request Format Send form data as application/x-www-form-urlencoded or multipart/form-data (for file uploads):
Field names are arbitrary — you define them in your HTML. All fields are optional; an empty form is valid. For a complete walkthrough of building an HTML form for email delivery, see our guide on connecting HTML forms to email. Special Fields Honeypot (spam protection) Add a hidden field named _gotcha to your form. Leave it empty. If a submission contains a non-empty value for this field, it will be rejected as spam: Spam detection response: 422 status with {"success": false, "message": "Spam detected."} Redirect (optional) Control where the user is redirected after submission using _redirect: For security, _redirect is only accepted if its host and scheme match the redirect URL configured in your form settings. Give it an absolute URL — a relative path like /thank-you carries no host, so it is ignored. Whenever the value is not accepted, the form's configured redirect is used instead, and the submission is still saved. Response Format Responses vary based on your form's redirect settings: No redirect configured Status: 200 {"success": true} Redirect configured Status: 302 (redirect to configured URL) Invalid or inactive token Status: 404 Monthly limit exceeded Status: 429 {"error": "Monthly limit exceeded"} Submission Limits Each plan includes a monthly submission quota. Once exceeded, new submissions are rejected until the next month or until you upgrade: Free 100 submissions/month Pro 10,000 submissions/month File Uploads File uploads are available on the Starter and Pro plans. Each file must meet these requirements: • Maximum size: 5 MB • Allowed types: JPEG, PNG, GIF, PDF If file uploads are submitted to a Free plan account, the submission is still accepted but files are not stored. The submission data will include a note that attachments were not saved. Webhooks Webhooks are available on the Pro plan. When a submission is received, CatchForm sends an HTTP POST to each active webhook URL with the following payload: { "form_id": 42, "submission_id": 1337, "data": { /* submitted fields */ }, "submitted_at": "2026-01-15T10:30:00.000000Z" } If you configured a webhook secret, each request includes an X-Webhook-Signature header containing an HMAC-SHA256 hash of the JSON payload, allowing you to verify the request's authenticity. Email Notifications When you create a form, you provide an email address where submissions should be delivered. Before the first submission is sent, we verify that you own this email address by sending a confirmation link. Each email notification includes the submission data. The email's Reply-To header is set to the email field from the submission (if present), allowing you to reply directly to the form's author. MCP Server MCP (Model Context Protocol) allows AI agents like Claude to manage forms and read submissions through CatchForm. Connect an AI assistant to create forms, retrieve data, and process submissions — and it's free on every plan, including Free. Getting your API token Visit your account settings, find the API tokens section, and create a new token. The value is shown only once — copy it immediately. Configuration The server runs on our side — there is nothing to install. Point your client at the URL below and pass your token. In Claude Code: claude mcp add --transport http catchform https://catchform.dev/mcp \ --header "Authorization: Bearer YOUR_TOKEN" Clients that keep servers in a JSON file — Cursor among them — take the same two values: { "mcpServers": { "catchform": { "type": "http", "url": "https://catchform.dev/mcp", "headers": { "Authorization": "Bearer YOUR_TOKEN" } } } } The token is a normal CatchForm API token, so the agent sees exactly what your account sees — its own forms and their submissions, nothing else. Revoke it on the account page and the agent loses access immediately. Available tools • list-forms — your forms with their endpoint URLs • get-form — one form: endpoint, notification address, redirect, ready HTML snippet • create-form — create a form; a confirmation link goes to the notification address • list-submissions — submissions of a form, newest first, with optional search Feeding these docs to an AI agent Two plain-text files exist for that: /llms.txt is a short map of the site, and /llms-full.txt is this documentation, the guides and the comparisons as one text. Both are generated from the pages you are reading, so they cannot drift out of date. Paste either URL into Cursor, Claude Code or any assistant that reads links, or connect the MCP server above and skip the copying. Learn More Need implementation examples? Check out our guides: • HTML form to email — The simplest integration • Contact form for Astro — Astro-specific example • Contact form for Hugo — Hugo template example Questions? Get in touch. ## Guide: HTML form to email https://catchform.dev/guides/html-form-to-email HTML Form to Email Send form submissions directly to your email without building a backend server. Just HTML, nothing else. ← Back to docs Overview This guide shows the simplest way to add a working contact form to any static site. No JavaScript, no build step, no backend infrastructure — just plain HTML. Why HTML Forms Need a Backend to Send Email A common misconception is that HTML can send email by itself. Here's what actually happens when someone submits a form in a browser: the browser collects the form data and makes an HTTP request to a server. That's it. Browsers cannot and do not send email directly. You might have seen the mailto: attribute or protocol, which looks like it sends email. In reality, it just opens your email client on your device (if one is configured). When someone clicks a mailto: link, the browser passes it to your operating system's email application, and you have to click "send" yourself. Nothing is automatically delivered, and the email address is exposed in your page's HTML source code for any bot to scrape. To actually send an email when someone submits a form, you need a server — something that receives the form data and hands it off to a mail service. This is what we mean by a "form backend." The Form Action: Your Bridge to Email Every form has an action attribute that tells the browser where to send the data:
...
The action URL must point to a server that knows how to handle form submissions. When someone clicks "send," the browser makes a POST request to that URL with all the form data in the request body. The server receives it, processes it, and can then send an email based on that data. CatchForm is that backend. You give each form a unique token, and the form's action points to CatchForm's endpoint. When data arrives, CatchForm validates it, stores it, and delivers it to your email inbox. Step 1: Create a Form Sign up for a free CatchForm account (no credit card required). You'll get a unique token for each form. Keep this token private — anyone with it can submit to your form. During setup, provide the email address where you'd like to receive submissions. We'll send you a confirmation link. Step 2: Add the HTML Form Paste this code into your HTML page where you want the form to appear:
Replace YOUR-TOKEN with the token from your form's settings. Step 3: What Happens After Submission When someone clicks "send," their browser makes a POST request to CatchForm with the form data. Here's the journey that data takes behind the scenes: Form is located. CatchForm looks up your form using the token in the action URL. If the form doesn't exist or has been deactivated, you'll get a 404 error. This prevents submissions to forms that are no longer active. Plan limit is checked. Every plan has a monthly submission limit. Free accounts get 100 submissions per month, while Pro accounts get 10,000. If your account has already reached this month's limit, the submission is rejected with a 429 (too many requests) error. Spam protection runs. CatchForm uses a honeypot field (the hidden input in your form named _gotcha) to catch bots. If a bot fills this field, the submission is rejected with a 422 error and marked as spam. Submission is stored. If all checks pass, CatchForm saves a copy of the submission in its database. This gives you a permanent record that you can view in your dashboard, even if your email filters send the message to spam. Email is sent. An email with all the form data is delivered to your inbox — but only if you've verified that email address. This prevents anyone from setting up a form that sends email to an arbitrary address. The email includes a "Reply-To" header set to the visitor's email address (detected from a field named email, Email, or e-mail, if its value is a valid address), so you can reply directly in your email client. Response is sent to the browser. If you configured a success redirect URL in your form's settings, the visitor's browser is redirected there. If no redirect was configured, CatchForm returns a JSON response with {"success": true}, which is useful for JavaScript-based forms that don't do a full page reload. You can also override the redirect URL per-submission by including a hidden input with name="_redirect", as long as it points to the same domain as your configured redirect. How CatchForm Compares to Mailto Links You might wonder why you need a form backend when you could just use a mailto: link. Here are the real differences: Aspect | Mailto: Link | CatchForm (Form Backend) | Requires email client | Yes — visitor must have a mail app | No — works on any device | Visitor sends the email | Yes — user clicks "send" in their client | No — server sends automatically | Email is stored | Only in visitor's Sent folder | Yes — you have a permanent record | Spam filtering | None — raw user input | Yes — honeypot field, spam never reaches your inbox | Email address visible | Yes — in page HTML | No — only on the server | Validation | None | Email address verified before sending | In short: mailto: is a fallback for when you want to let someone email you directly. A form backend is the professional choice because it actually sends the email, stores it, and protects your inbox from spam. Customization Custom Field Names Change the name attribute on any input to customize what you see in your email. Add as many fields as you need: Success Redirect By default, the form submission redirects to a success page of your choosing. Configure this in your form's settings on CatchForm. If you want to override it per-submission (for A/B testing or multiple forms on one page): The redirect URL must be on the same domain as your form's configured redirect URL. This protects against using CatchForm as a redirect service. Spam Protection The line is a honeypot field. Bots will try to fill it; if they do, we reject the submission as spam. Keep it in your form. Common Patterns Newsletter Signup
Contact Form with File Upload
File uploads are only available on the Pro plan. Remember to use enctype="multipart/form-data" when uploading files. Get Started Ready to add a contact form? Sign up for free and get your first 100 submissions included. ## Guide: contact form for Astro https://catchform.dev/guides/contact-form-astro Contact Form for Astro Build a contact form component for your Astro site that sends submissions directly to your email without any backend server. ← Back to docs Overview This guide shows how to create a reusable contact form component in Astro that works without a backend. The form sends submissions directly to CatchForm, which delivers them to your inbox. Prerequisites An Astro project (v3.0 or later) A CatchForm account with an active form Step 1: Set Up CatchForm Sign up for CatchForm and create a new form. You'll receive a unique token. Store it in your .env file: PUBLIC_CATCHFORM_TOKEN=your-token-here The PUBLIC_ prefix makes it safe to expose in the browser (the token is already public since the form accepts submissions from any origin). Step 2: Create the ContactForm Component Create a new file src/components/ContactForm.astro: --- const token = import.meta.env.PUBLIC_CATCHFORM_TOKEN; ---
Step 3: Use the Component Import and use the component in any Astro page or layout: --- import ContactForm from '../components/ContactForm.astro'; --- Contact Us

Get in Touch

Customization Add a Success Message After form submission, redirect the user to a success page. In your CatchForm dashboard, configure the redirect URL (e.g., /thank-you), then create a corresponding Astro page. Add More Fields Simply add more form groups to the component. Change the name attribute to customize how the field appears in your email:
Style with Your Design System The component uses local scoped styles. Replace them with your own CSS utilities (Tailwind, Pico, etc.) or external stylesheets. Pro Tips File Attachments Pro plan users can accept file uploads. Add an input with type="file" and ensure the form has enctype="multipart/form-data". Allowed types: JPEG, PNG, GIF, PDF. Maximum size: 5 MB. Client-Side Validation The form uses HTML5 validation attributes (required, type="email"). Browsers enforce these, but always validate on the server side (CatchForm does). Spam Protection The honeypot field is already included in the component. Bots will fill it and their submissions will be rejected automatically. To understand how raw HTML forms submit data without any framework overhead, check our plain HTML form submission guide. Next Steps Your form is now live. Check your inbox for submissions. Need more help? • Full API documentation • Explore Pro features • Contact support ## Guide: contact form for Hugo https://catchform.dev/guides/contact-form-hugo Contact Form for Hugo Build a contact form partial for your Hugo site that sends submissions directly to your email without any backend server. ← Back to docs Overview This guide shows how to create a reusable contact form partial in Hugo that works without a backend. The form sends submissions directly to CatchForm, which delivers them to your inbox. Prerequisites A Hugo site (v0.100 or later) A CatchForm account with an active form Step 1: Set Up CatchForm Sign up for CatchForm and create a new form. You'll receive a unique token. Store it in your Hugo site's config or pass it via parameters. Option A: Add it to your config file (hugo.toml): [params] catchformToken = "your-token-here" Step 2: Create the Contact Form Partial Create a new file layouts/partials/contact-form.html:
Step 3: Use the Partial Include the partial in any layout or content page using the partial function: {{ define "main" }}

{{ .Title }}

{{ .Content }} {{ partial "contact-form" . }}
{{ end }} In Markdown files, use shortcodes to include the partial: {{< partial "contact-form" . >}} Customization Add a Success Message After form submission, redirect the user to a success page. In your CatchForm dashboard, configure the redirect URL (e.g., /thank-you), then create a corresponding Hugo page. Add More Fields Simply add more form groups to the partial. Change the name attribute to customize how the field appears in your email:
Pass Token as Parameter If you prefer not to store the token in config, pass it as a parameter to the partial: {{ partial "contact-form" (dict "token" "your-token-here") }}
...
Style with Your Theme The partial uses inline scoped styles. Replace them with your theme's CSS or remove the