> ## Documentation Index
> Fetch the complete documentation index at: https://docs.lekalao.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscription forms

> Subscribe people from your own site, in HTML or in JavaScript.

Every list can take subscriptions from a form placed on any site: no widget to load, just a `POST`.

## Switch the form on

In the list's **Settings** tab, the **Subscription form** section:

<ParamField path="Accept subscriptions from external forms" type="boolean" required>
  While the box is unticked, the form's address answers "not found".
</ParamField>

<ParamField path="Allowed domains" type="one per line">
  Only forms served from these domains (and their subdomains) are accepted,
  going by the `Origin` or `Referer` header. Leave it empty to accept any
  site.
</ParamField>

<ParamField path="Redirect after subscribing, Redirect after unsubscribing" type="URL">
  Where to send the person after the form is submitted: **subscribed**,
  **waiting for confirmation** (double opt-in) and **after unsubscribing**.
  Without a redirect, Lekalao shows its own thank-you page in your
  [brand](/content/brand) colours.
</ParamField>

## The form, ready to use

Copy the block shown in the settings. It looks like this:

```html theme={null}
<form
    method="POST"
    action="https://lekalao.example.com/subscribe/9d5c2a1e-8f3b-4c7a-9e21-3b8f0c6d4a12"
>
    <input type="email" name="email" placeholder="you@example.com" required />
    <input type="text" name="first_name" placeholder="First name" />
    <input
        type="text"
        name="website"
        style="display:none"
        tabindex="-1"
        autocomplete="off"
    />
    <button type="submit">Subscribe</button>
</form>
```

### The fields it takes

| Field                     | Required | Notes                                                                                   |
| ------------------------- | -------- | --------------------------------------------------------------------------------------- |
| `email`                   | yes      | 255 characters at most.                                                                 |
| `first_name`, `last_name` | no       |                                                                                         |
| `locale`                  | no       | The language they read in: `fr`, `en`, `pt-BR`… Useful on a multilingual site.          |
| `tags[]`                  | no       | 20 at most. **Only tags that already exist on the list** are added; others are ignored. |
| `website`                 | —        | The bot trap: it must stay empty and hidden.                                            |

<Warning>
  Keep the hidden `website` field. A bot fills in every field: when this one
  is not empty, Lekalao answers as if the subscription had worked, without
  subscribing anyone.
</Warning>

### What happens next

* **A list without double opt-in**: the person is subscribed; automations for "someone subscribes" start; the welcome e-mail goes out when it is switched on.
* **A list with double opt-in**: they receive the confirmation e-mail and see the "Check your inbox" page.
* **An address already subscribed**: the first name, last name and language you send update their record, tags are added, and the success page appears.
* **Someone who had unsubscribed**: filling in the form counts as subscribing again.
* **A blocked address** (on the suppression list): the success page appears all the same; Lekalao never reveals that an address is blocked.

Every subscription is written to the consent log with the IP address and the page it came from.

## Sending it with JavaScript

With the `Accept: application/json` header, the form answers in JSON instead of redirecting. It takes requests from other sites (CORS); the allowed-domain check is still done by Lekalao:

```js theme={null}
const response = await fetch('https://lekalao.example.com/subscribe/9d5c2a1e-8f3b-4c7a-9e21-3b8f0c6d4a12', {
  method: 'POST',
  headers: { 'Accept': 'application/json', 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'ada@example.com', first_name: 'Ada', locale: 'en', tags: ['newsletter'] }),
});

const { status } = await response.json(); // "subscribed" or "pending"
```

| Code  | Means                                                                      |
| ----- | -------------------------------------------------------------------------- |
| `200` | `{"status": "subscribed"}` or `{"status": "pending"}` (confirmation sent). |
| `403` | The site it came from is not among the allowed domains.                    |
| `404` | The form is not switched on for this list.                                 |

More, with React and server-side examples, in [Forms](/developers/forms).
