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

# FAQ

<AccordionGroup>
  <Accordion title="Do I need a token before submitting?">
    No. Every submission path — including a plain `<form>` with JavaScript disabled entirely — hits the same public endpoint directly, with no round-trip required first. See [Introduction](/introduction) for why this is deliberate.
  </Accordion>

  <Accordion title="Which framework should I use?">
    Whichever matches your project — there's no "recommended" tier that gets better treatment. React/Vue/Svelte/Angular all get the same `useRaykoiForm` lifecycle management; plain HTML gets it automatically via `submit.js`; anything else uses the headless `client.form(id).submit()` directly. See [Integrations](/integrations/overview).
  </Accordion>

  <Accordion title="Can I use Raykoi with no JavaScript at all?">
    Yes — a plain `<form method="POST">` works, protected by honeypot, rate limiting, and origin checks (CAPTCHA can't run without JS, so it's excluded from that path's protection). See [No JavaScript](/integrations/no-javascript).
  </Accordion>

  <Accordion title="Can I style the Basic HTML runtime's messages?">
    Yes, entirely — Raykoi writes plain markup with stable class/attribute hooks (`.raykoi-message`, `.raykoi-field-error`, `data-raykoi-state`) and adds zero inline styles. Add your own rules to your page's stylesheet. See [Markup Hooks](/integrations/options-reference/markup-hooks).
  </Accordion>

  <Accordion title="Do file uploads go through my server?">
    No — a file uploads directly from the visitor's browser to storage via a short-lived signed URL. Your server (and Raykoi's own API server) never sees the file bytes unless you explicitly proxy them yourself. See [File Uploads](/essentials/file-uploads).
  </Accordion>

  <Accordion title="What happens to a submission Raykoi thinks might be spam?">
    It's stored, never silently dropped — just filtered into the **Suspicious** tab instead of **Valid**, for you to review. Only a filled honeypot or a verified-invalid CAPTCHA token blocks a submission from being stored at all.
  </Accordion>

  <Accordion title="Is there a sandbox / test mode?">
    API keys support a `test` type (`rk_test_...`) alongside `live` — use a test key while developing so submissions don't mix into real data on the backend/Server-Data-API side. There's no separate test *environment* for public submissions (the browser-facing endpoint doesn't distinguish); use a dedicated test form during development instead.
  </Accordion>

  <Accordion title="How do retries work for a submission?">
    Every submission carries an `Idempotency-Key` (auto-generated by the SDK if you don't supply one) — retrying with the *same* key and *same* payload returns the original result instead of creating a duplicate, so a flaky network or a double-click never double-submits.

    ```javascript theme={null}
    // Safe to call again with the same key after a timeout — never double-submits
    await client.form('YOUR_PUBLIC_ID').submit(data, { idempotencyKey: 'my-stable-key' });
    ```

    See [Submissions](/essentials/submissions#idempotency).
  </Accordion>

  <Accordion title="Can I get notified the moment someone submits?">
    Configure a [webhook](/essentials/integrations/webhook) — your own endpoint, Slack, Discord, or Telegram — with a fully structured payload.
  </Accordion>

  <Accordion title="What's the difference between the public API and the Server Data API?">
    The public API (`/api/v1/forms/p/...`, `/api/v1/submit/p/...`) is what a browser calls directly — no secret required, protected by spam signals instead of a credential. The [Server Data API](/api-reference/server-data-api) (`/api/v1/server/...`) is secret-key-authenticated, server-side only, and exists for your backend to *read* data it owns — never called from a browser.
  </Accordion>
</AccordionGroup>
