# Forms API

Create and manage signup forms. Each form has a submit URL you can post to from your own site. All routes need a bearer API key (see [API Overview](/docs/api/overview)).

For the dashboard builder, embed code and display options, see [Forms](/docs/platform/forms).

## The form object

```json
{
  "id": "clx...",
  "name": "Footer signup",
  "listId": "clx...",
  "fields": ["firstName"],
  "style": {},
  "successMessage": "Thanks! You're subscribed.",
  "createdAt": "2026-10-01T09:00:00.000Z",
  "updatedAt": "2026-10-01T09:00:00.000Z",
  "embedUrl": "https://flomailr.com/api/forms/clx.../submit"
}
```

- `fields` lists the optional fields shown next to email, for example `["firstName", "lastName"]`.
- `style` holds the form's look (button text and colours, background, corner radius). It is `{}` until the builder or a `PATCH` sets it.
- `listId` is the list that new subscribers join. It can be `null`.
- `embedUrl` is the URL the form submits to.

## List forms

```text
GET /api/v1/forms
```

Query: `limit`, `after` (see [pagination](/docs/api/overview)).

## Create a form

```text
POST /api/v1/forms
```

```json
{
  "name": "Footer signup",
  "listId": "clx...",
  "fields": ["firstName", "lastName"],
  "successMessage": "You're in."
}
```

- `name` is required.
- `listId` is optional. If given it must be a list in your workspace (`404` otherwise).
- `fields` defaults to `["firstName"]`. Non-string entries are dropped.
- `successMessage` defaults to "Thanks! You're subscribed."

Returns `201`.

## Get, update and delete

```text
GET    /api/v1/forms/:id
PATCH  /api/v1/forms/:id
DELETE /api/v1/forms/:id
```

`PATCH` accepts `name` (cannot be empty), `listId` (a list id, or `null` to detach), `fields` (an array of strings), `successMessage` and `style` (an object). `DELETE` returns `204`.

The API does not expose a form's display mode or trigger settings. Set those in the dashboard.

## Submitting a form

The `embedUrl` is a public endpoint. It needs no API key, so a browser on your own site can post to it directly. It allows cross-origin requests.

```text
POST /api/forms/:id/submit
```

Send JSON or a standard form post with `email` (required) and optionally `firstName` and `lastName`:

```bash
curl -X POST https://flomailr.com/api/forms/FORM_ID/submit \
  -H "Content-Type: application/json" \
  -d '{"email":"ada@example.com","firstName":"Ada"}'
```

A successful post returns the form's success message:

```json
{ "ok": true, "message": "Thanks! You're subscribed." }
```

- An invalid or missing email returns `400` with `{ "error": "..." }`.
- Each IP address can submit five times in ten minutes. After that the endpoint returns `429`.
- An address that has bounced returns `400` ("This email address cannot be re-subscribed."). Other suppressed addresses get the normal success message and are left unchanged.
- Whether the new contact is subscribed straight away or must confirm by email first depends on the signup rules. See [Double Opt-In](/docs/concepts/double-opt-in).
