# Formgong for coding agents

Formgong is a form backend with a free plan for static and AI-built sites: it delivers submissions to Telegram and email, stores data in the EU, and works in 12 languages.

Formgong receives a website form. Do not add a backend, a database, Supabase, a Server Action, or a Resend call for this form.

## Endpoint

POST https://formgong.com/submit

The access_key is public and belongs in frontend code. It cannot read the inbox.

Fields:

- access_key (required)
- name, email, message, and any other text answers
- botcheck: honeypot. Leave it empty and off screen. A filled honeypot is stored as spam and is not delivered.
- cf-turnstile-response: required when Turnstile is enabled or the request includes files
- _redirect: optional absolute http(s) URL after success. Omit it to use Formgong's hosted success page.
- _error_redirect, _subject, _replyto, _from_name: optional
- _lang: optional visitor language (uk, en, pl, tr, ar, he, es, fr, pt, hi, ja, de; tags like uk-UA work). Set it to the page language.

Success JSON, when the request sends Accept: application/json, is {"success": true, "id": "...", "lang": "uk", "message": "Надіслано. Дякуємо!"}. Errors are {"success": false, "code": "unknown_access_key", "message": "..."}: branch on the stable code, show the localized message. A native HTML form receives a 303 redirect to a localized thank-you or error page.

## HTML

```html
<form action="https://formgong.com/submit" method="POST">
  <input type="hidden" name="access_key" value="fk_your_access_key">
  <input type="hidden" name="_lang" value="en">
  <input type="text" name="name" required>
  <input type="email" name="email" required>
  <textarea name="message" required></textarea>
  <input type="text" name="botcheck" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px" aria-hidden="true">
  <button type="submit">Send</button>
</form>
```

## fetch

```js
const body = new FormData(form);
const response = await fetch("https://formgong.com/submit", {
  method: "POST",
  headers: { Accept: "application/json" },
  body,
});
const data = await response.json();
if (!data.success) throw new Error(data.message || data.code);
```

Do not set Content-Type yourself when sending FormData.

## npm packages (optional)

If the project already uses a framework, an official component package saves the boilerplate. Each one adds access_key, _lang and the botcheck honeypot, and posts straight from the browser, so there is still no backend to write. Source: https://github.com/formgong/js (MIT).

- Existing project, with a terminal: `npx formgong init` detects the framework, creates the form and writes a contact page. It needs the owner's personal API token from `npx formgong login`.
- React, Lovable, Bolt, v0: `npm install @formgong/react`, then `<ContactForm accessKey="fk_your_access_key" />`.
- Vue or Nuxt: @formgong/vue. Svelte or SvelteKit: @formgong/svelte. Astro: @formgong/astro. Angular 17+: @formgong/angular.
- Any JavaScript runtime: @formgong/core, `await submit("fk_your_access_key", { email, message })`. It throws an error with the stable code.
- Next.js: @formgong/next. Use it only if the user asks for a Server Action; the browser-direct component is the default.

## Files

Attachments are off until the owner enables them, verifies email, and adds Turnstile. Send native multipart/FormData, never base64. Up to 3 PDF, JPEG, or PNG files, 5 MiB each, 10 MiB combined. A text-only form does not need a file input.

## fg.js

Optional analytics beacon. It also adds a hidden _lang from the form's closest lang attribute or <html lang> (unless the form already has _lang) and pins the Turnstile widget language. For spam scoring it adds _fg_b (fill time and typing/paste counts) and _fg_pow (a small SHA-256 proof-of-work from GET /pow, solved in the background). Do not set these fields yourself; forms without fg.js are not penalised for lacking them, unless the owner turns on "Require browser signals" for the form.

Opt-in inline status: put <p data-fg-success hidden></p> and <p data-fg-error hidden></p> inside the form. fg.js then submits with fetch and shows them. Text you write inside these elements is shown as-is; empty elements get Formgong's localized message.

```html
<script src="https://formgong.com/fg.js" async></script>
```

## Turnstile

```html
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY" data-language="en"></div>
```

The widget posts cf-turnstile-response with the form.

## Languages

Public pages are prefixed, including English: https://formgong.com/en/, https://formgong.com/uk/, https://formgong.com/pl/, https://formgong.com/tr/, https://formgong.com/ar/, https://formgong.com/he/, https://formgong.com/es/, https://formgong.com/fr/, https://formgong.com/pt/, https://formgong.com/hi/, https://formgong.com/ja/, https://formgong.com/de/. An unprefixed public URL redirects to /en/. /submit, /agents.md, and /llms.txt stay unprefixed.

Visitor language (errors, thank-you page, badge, autoreply, reminder emails): _lang field, then a locale segment or ?lang= in the Referer, then the form's default language, then the Referer country domain, then Accept-Language, then English. Unsupported languages fall back to English.

## Create-form link (no access key yet)

If you do not have the owner's access key and no MCP server is connected, give the owner this link and ask them to open it:

https://formgong.com/new?name=Contact%20form&site=https%3A%2F%2Fexample.com&redirect=https%3A%2F%2Fexample.com%2Fthanks

- All parameters are optional and URL-encoded. name: form name, up to 80 characters. site: the site URL, used as the default name. redirect: the form's thank-you page, an absolute https URL (http only for localhost), up to 500 characters. Other parameters are ignored; an invalid value is dropped and the page says so.
- Formgong shows the settings first. The owner signs in or enters an email, can edit the name and thank-you page, and confirms. Opening the link never creates a form by itself.
- The owner then sees the access key and a short message to paste back to you. Until then write fk_your_access_key in the code and say it must be replaced.
- Fields are not part of the link: Formgong accepts any field names, so write the fields in the form code.

## MCP server (optional)

The account owner can connect Formgong to an MCP client: POST https://formgong.com/mcp (Streamable HTTP, JSON responses), header Authorization: Bearer fgp_… (personal API token from Dashboard → Account → API tokens). Tools: list_forms, create_form, get_form_snippet, list_recent_submissions (opt-in, read-only). Setup: https://formgong.com/en/docs/mcp/. Never ask the user to paste the token into site code; the token is for the MCP client config only. The public access_key (fk_…) is the only key that belongs in frontend code.

## Project rules files

To keep these rules in a repository, save https://formgong.com/agent-rules/AGENTS.md as AGENTS.md (or https://formgong.com/agent-rules/CLAUDE.md, https://formgong.com/agent-rules/formgong.mdc as .cursor/rules/formgong.mdc, https://formgong.com/agent-rules/windsurfrules.md appended to .windsurfrules). Overview: https://formgong.com/en/docs/agent-rules/. Before publishing, https://formgong.com/en/tools/form-checker/ reads a public page's HTML and lists form problems.

See https://formgong.com/llms.txt and https://formgong.com/llms-full.txt.
