Skip to content

JSON submissions

You can send a submission with JavaScript instead of a normal form post, for example to show a message without leaving the page.

The request

  • POST to the form's endpoint.
  • Body: a flat JSON object. Each member is one field.
  • Header Content-Type: application/json.

Field values can be strings, numbers, booleans or null, or arrays of those. Numbers and booleans are stored as written, null becomes an empty value, and an array becomes a field with several values. Nested objects are not allowed.

const response = await fetch("https://api.letterpost.eu/f/k3v9q2", {
  method: "POST",
  headers: { "Content-Type": "application/json", "Accept": "application/json" },
  body: JSON.stringify({
    email: "jane@example.org",
    message: "Hello!",
    topics: ["pricing", "support"],
  }),
});

if (response.ok) {
  // Show a thank-you message.
} else {
  const { error } = await response.json();
  // error is a message, or an object with one message per field.
}

You can also send FormData as multipart/form-data or application/x-www-form-urlencoded. Add Accept: application/json to get JSON answers instead of redirects.

The answer

A successful submission returns status 200:

{"status": "received"}

A rejected one returns the error status and an error member. The codes are listed in Errors and redirects.

_redirect and _redirect_error have no effect on JSON requests.

Captchas

With a captcha, send the widget's answer in the field the widget uses: altcha, cf-turnstile-response or frc-captcha-response. The easiest way is to build the body from the form with new FormData(form), which includes the widget's hidden field.

Cross-origin requests

letterpost answers the browser's preflight request, so fetch from your own website works. If the form has a list of allowed websites, your site must be on it.