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

# Files and CAPTCHA

> Upload files and protect an Endpoint form from automated submissions.

Endpoint forms can accept file uploads and use the same CAPTCHA settings as Hosted forms. Because an Endpoint form does not include a user interface, you add the file input and CAPTCHA widget to your own page.

## Upload a file

Use `FormData` so the browser sends `multipart/form-data`. Do not set the `Content-Type` header yourself—the browser adds the required boundary.

```html theme={null}
<form id="application-form">
  <input name="name" required />
  <input name="resume" type="file" accept=".pdf,.doc,.docx" />
  <button type="submit">Send application</button>
</form>

<script>
  const form = document.querySelector('#application-form');

  form.addEventListener('submit', async (event) => {
    event.preventDefault();

    const data = new FormData(form);

    const response = await fetch('https://api.surveyowl.co/v1/submit/YOUR_FORM_PUBLIC_KEY', {
      method: 'POST',
      body: data,
    });

    if (!response.ok) {
      const result = await response.json();
      const message = typeof result.error === 'string'
        ? result.error
        : result.error?.message;
      throw new Error(message || 'The file could not be sent.');
    }
  });
</script>
```

Accepted file types include common images, PDFs, Microsoft Office documents, text and CSV files, ZIP files, and GZIP archives. File size, file count, and storage allowances depend on the form owner's plan. An unsupported or oversized file is rejected before the response is saved.

## Enable CAPTCHA

1. Open the Endpoint form and select **Settings**.
2. Under **Security**, open the **Captcha provider** menu and choose reCAPTCHA v2, reCAPTCHA v3, hCaptcha or Cloudflare Turnstile. Endpoint forms use your own provider account.
3. Add the public site key and the secret key from that provider.
4. Register every domain where your form appears with the provider, including localhost while testing.
5. Make sure the **CAPTCHA** switch is on and save.

Next, render that provider's widget or script in your frontend. Send its token alongside the other answers using the field shown in **Settings**:

| Provider | Token field |
| - | - |
| reCAPTCHA v2 or v3 | `g-recaptcha-response` |
| hCaptcha | `h-captcha-response` |
| Cloudflare Turnstile | `cf-turnstile-response` |

CAPTCHA tokens normally expire and cannot be reused. Generate a fresh token for every submission. If the endpoint returns `captcha_required`, `captcha_expired_or_reused`, or `captcha_failed`, show a useful message and let the visitor try again.

<Warning>
  **Keep the CAPTCHA secret private.** The site key is public, but the secret belongs only in the form's Settings. Never put it in HTML or browser JavaScript.
</Warning>

## Honeypot protection

Honeypot screening runs on every submission and needs no provider account. Any field whose name contains `honeypot` is treated as a decoy: it is never saved as an answer, and if it arrives with a value the submission is silently dropped.

On an Endpoint form you have to add the decoy yourself. Hide it from real visitors and keep it out of the tab order and autofill:

```html theme={null}
<div style="position:absolute;left:-9999px" aria-hidden="true">
  <input name="contact_honeypot_field" type="text" tabindex="-1" autocomplete="off" />
</div>
```

The name can be anything that contains `honeypot`, so pick one that blends in with your other fields.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.