> ## 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.

# Submit a Form

> The one endpoint every integration ultimately calls.

Accepts `application/json` (the normal path — used by the SDK, `submit.js`, and raw `fetch`) or `application/x-www-form-urlencoded` (the plain `<form method="POST">` no-JS path). The response shape changes based on which one you sent — see [No JavaScript](/integrations/no-javascript) for that variant's redirect-based behavior.

<ParamField path="public_id" type="string" required>
  The form's public ID, shown in the dashboard.
</ParamField>

<ParamField body="data" type="object" required>
  Field values keyed by field name. A file field's value is a file reference object (`{ path, originalFilename, mimeType, sizeBytes }`) obtained from [Get an Upload URL](/api-reference/upload-url), not the raw file — see [File Uploads](/essentials/file-uploads).
</ParamField>

<ParamField body="captcha_token" type="string">
  Required if the form has CAPTCHA configured and you're not authenticating with an API key. Acquired client-side from whichever provider the form uses.
</ParamField>

<ParamField body="metadata" type="object">
  Arbitrary extra data to attach to the submission — not validated against the schema, not shown as a form field, just stored alongside it.
</ParamField>

<ParamField body="redirect" type="string">
  No-JS path only. A same-origin (or `allowed_origins`-matching) URL to redirect to after success or failure.
</ParamField>

<ParamField header="Authorization" type="string">
  `Bearer rk_live_...` — a secret API key. Authenticates the request as server-to-server and skips the CAPTCHA gate entirely.
</ParamField>

<ParamField header="Idempotency-Key" type="string">
  A key unique to this logical submission attempt. Reusing it with the same payload returns the original result instead of creating a duplicate; reusing it with a different payload is rejected. Auto-generated by the SDK if you don't supply one.
</ParamField>

### Response

<ResponseField name="success" type="boolean">
  Always `true` on a 201 — a non-2xx status is always an error body instead.
</ResponseField>

<ResponseField name="submission_id" type="string">
  The submission's public ID.
</ResponseField>

<ResponseField name="submission_number" type="number">
  A per-form sequential number — useful for a human-readable reference ("submission #42"), not for sorting (use `created_at`).
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.raykoi.com/api/v1/submit/p/YOUR_PUBLIC_ID" \
    -H "Content-Type: application/json" \
    -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
    -d '{"data": {"email": "user@example.com", "name": "Alice"}}'
  ```

  ```javascript SDK theme={null}
  import { createClient } from '@raykoi/sdk';

  const client = createClient();
  await client.form('YOUR_PUBLIC_ID').submit({
    email: 'user@example.com',
    name: 'Alice',
  });
  ```
</RequestExample>

<ResponseExample>
  ```json 201 Success theme={null}
  {
    "success": true,
    "submission_id": "sub_pub_1a2b3c",
    "submission_number": 42
  }
  ```

  ```json 422 Validation failed theme={null}
  {
    "error": "Validation failed",
    "errors": [
      { "field": "email", "fieldId": "email", "message": "Enter a valid email address", "type": "pattern" }
    ]
  }
  ```

  ```json 403 Blocked as spam theme={null}
  { "error": "This submission was flagged as spam. If you believe this is a mistake, please reload the form and try again." }
  ```
</ResponseExample>
