# Getting started

Five steps, no SDK. If your site can render an HTML form, it can use Formwire.

## 1. Create a form

Sign in at [app.formwire.com](https://app.formwire.com). Your first workspace is created for you and your sign-in address is verified as its first linked email, so it can receive submissions straight away.

Choose **Create form**, give it a name and the site it lives on, and pick who gets the email. A form doesn't need a recipient: leave them out and submissions are only stored for the dashboard, the [API](/docs/api) and [MCP](/docs/mcp).

## 2. Copy the access key

The access key is on the form's **Settings** tab, under **General**, with **Copy** and **Rotate** beside it. The key is a public ID: it can only deliver submissions to you, so it's safe to ship in your HTML and commit to a repo. If a key is ever abused, rotate it; the old key keeps working for seven days so live sites can be updated.

## 3. Paste the form

Point the form's `action` at `https://formwire.io/submit` and add the key as a hidden `access_key` field. The form's **Fields** tab writes this code for you, with your key filled in. Adding fields there is optional: the form accepts any field it sends, and listing one only sets its label, its order and the code written for it. Field names are up to you; `name`, `email` and `phone` are recognised as the sender's details, and a few option fields such as `subject` and `redirect` change how the email and the thank-you page behave. The [submit endpoint reference](/docs/submit) lists all of them.

```html
<form action="https://formwire.io/submit" method="POST">
  <input type="hidden" name="access_key" value="YOUR-ACCESS-KEY" />
  <input type="hidden" name="redirect" value="https://example.com/thanks" />

  <label>Name <input type="text" name="name" /></label>
  <label>Email <input type="email" name="email" required /></label>
  <label>Message <textarea name="message" required></textarea></label>

  <!-- Spam trap: keep it off-screen and empty. Bots fill it in; people never see it. -->
  <input type="text" name="fax" tabindex="-1" autocomplete="off" style="position:absolute;left:-9999px" aria-hidden="true" />

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

```js
const res = await fetch("https://formwire.io/submit", {
  method: "POST",
  headers: { "Content-Type": "application/json", Accept: "application/json" },
  body: JSON.stringify({
    access_key: "YOUR-ACCESS-KEY",
    name: "Ada Lovelace",
    email: "ada@example.com",
    message: "Hello from fetch",
  }),
});
const body = await res.json();
if (body.success) {
  console.log("Stored as", body.data.submission_id);
} else {
  console.error(body.error.code, body.message);
}
```

```bash
curl https://formwire.io/submit \
  -H "Accept: application/json" \
  -F access_key=YOUR-ACCESS-KEY \
  -F email=ada@example.com \
  -F message='Hello from curl'
```

The `fax` input is the form's honeypot. Keep it hidden and empty: a submission that fills it in lands in the Spam folder and nobody is emailed. You can rename it under **Settings**, **Spam & security**; the code on the **Fields** tab always uses the current name.

## 4. Send a test

Submit the form from your page, or use **Send test submission** on the **Fields** tab, which stores a sample submission and sends the notification without counting toward your monthly usage. A JSON caller gets this back:

```json title="Response"
{
  "success": true,
  "message": "Submission received.",
  "data": {
    "submission_id": "7c1e9b2a-4f3d-4e8a-9b1c-2d5f6a7b8c9d",
    "name": "Ada Lovelace",
    "email": "ada@example.com",
    "message": "Hello from fetch"
  }
}
```

A plain HTML post is answered with a redirect instead: to your `redirect` URL if you set one, otherwise to a hosted thank-you page.

## 5. See it in the inbox

Every confirmed recipient gets an email within seconds. The submission also appears on the form's **Submissions** tab, where you can search, star, archive and export it as CSV, and each submission shows whether its email and webhooks went out.

To copy more people in, choose **Add CC or BCC** under **Send submissions to** in the form's **Settings › Email**. CC and BCC addresses are linked emails too, so each one confirms before it receives anything.

Submissions are kept for 30 days and then deleted for good. Change that under **Settings › Files & data › Keep submissions for**, from 7 days up to a year. Spam is always cleared after 30 days.

## Where your data is stored

Each workspace keeps its submissions in one region, the United States or the European Union. You choose it when you create the workspace (on the welcome page, or with **Create workspace** in the workspace menu). Every plan includes both regions. A workspace's region can't be changed later; to move, create a workspace in the other region. **Settings**, **Workspace** shows which region a workspace uses, and so does `GET /workspace` in the [API](/docs/api).

In an EU workspace, submissions, their uploaded files and their nightly backups are stored only in Cloudflare's EU jurisdiction. Your account, forms and settings are stored in the United States for every workspace, and notification emails are sent through Amazon SES in the United States.

## Where next

- [Submit endpoint](/docs/submit): The URL, every field it reads, responses and errors.
- [Spam protection](/docs/spam): Honeypot, rate limits, captchas and allowed domains.
- [Webhooks](/docs/webhooks): Signed JSON for each submission, with retries.
- [API](/docs/api): Read and manage forms and submissions with an API key.
- [MCP server](/docs/mcp): Let Claude Code, Cursor or ChatGPT run your forms.
- [One-prompt setup](/docs/prompt): Paste one prompt into Lovable, v0, Bolt or Cursor.
- Building with an AI tool? Paste the [one-prompt setup](/docs/prompt), or point your agent at [formwire.com/llms.txt](/llms.txt).