A Cloudflare Worker that receives browser submissions and forwards them to SmartForm AI. Use this instead of the Vercel Function when you want to host everything on Cloudflare.
The endpoint accepts a standard HTML form POST or JSON via AJAX. Two kinds of fields:
Your form fields �name, email, message, whatever you
want. Every non-reserved field lands in your dashboard as a column in
the submissions table.
Reserved fields �names starting with _ are interpreted by
the API, not stored:
| Field | Purpose |
|---|---|
_gotcha |
Honeypot. Keep it empty. Hidden from humans via CSS; bots fill it automatically. Any non-empty value silently drops the submission. Add this to every form. |
_hp_email / _website / _url / _phone |
Honeypot aliases for _gotcha (WordPress / WPForms / Contact Form 7 migrations). Same drop semantics. |
_next |
Same-origin URL to redirect to after a successful submission. Browser POST results in a 302 here. AJAX calls (with Accept: application/json) get the same value back as next_url in the JSON response. Only http(s) and in-site paths allowed. |
_subject |
Override the AI-generated email subject line. Max 200 chars; control characters stripped. |
X-Gotcha header |
Same as _gotcha for JSON requests where you can't add a hidden form field. |
Field names are Formspree-compatible �migrating from
formspree.io/f/{form_id} requires no renaming.
- Get a form ID at https://usesmartform.com/dashboard.
- Configure secrets:
git clone https://github.com/smartformai/smartform-example-serverless-cloudflare.git cd smartform-example-serverless-cloudflare wrangler kv:namespace create SESSIONS # optional �only if you add rate-limit caching npx wrangler secret put SMARTFORM_ENDPOINT # https://api.usesmartform.com npx wrangler secret put SMARTFORM_FORM_ID # your_real_id npx wrangler deploy
- Browser calls
POST https://your-worker.workers.dev/submit. The Worker forwards to SmartForm.
// src/index.ts
export interface Env { SMARTFORM_ENDPOINT: string; SMARTFORM_FORM_ID: string; }
export default {
async fetch(req: Request, env: Env): Promise<Response> {
if (req.method !== 'POST' || new URL(req.url).pathname !== '/submit') {
return new Response('Not Found', { status: 404 });
}
const body = await req.json();
const r = await fetch(`${env.SMARTFORM_ENDPOINT}/api/v1/f/${env.SMARTFORM_FORM_ID}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'Accept': 'application/json' },
body: JSON.stringify(body),
});
return new Response(await r.text(), {
status: r.status,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
},
});
},
};wrangler.toml declares the Worker name and compatibility date; deploy with wrangler deploy.
index.html is a plain HTML page that posts JSON to /submit on the Worker origin and
renders the response inline.
POST {endpoint}/api/v1/f/{form_id}�JSON or form-data, no API key.- Response:
{ success, message, submission_id, is_spam, intent, next_url }.
For the full contract, see https://usesmartform.com/docs.
Yes. AI spam filtering is enabled by default on every plan. AI intent classification and high-value lead detection require a paid plan (Pro or Business) �the dashboard enforces this and returns HTTP 402 if you try to enable them on a free workspace.
No. The form posts directly to a public endpoint using only an 8-char
form ID, which is non-enumerable. The example also includes a hidden
_gotcha honeypot field so naive bots cannot submit.
The Worker hides the form ID and lets you add KV-based rate limiting in front of the public endpoint. Pure edge �no cold starts.
Vercel Functions proxy | Cloudflare Pages contact form | Astro contact form
MIT.