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

# Submissions

> Retrieve, create, and delete form submissions via the REST API.

A submission represents one completed response to a form. Each submission stores the respondent's answers keyed by field ID, along with metadata such as IP address and referrer.

***

## List submissions

`GET /forms/{id}/submissions`

Returns a paginated list of submissions for a specific form, ordered from newest to oldest.

### Path parameters

<ParamField path="id" type="string" required>
  The form ID whose submissions you want to retrieve.
</ParamField>

### Query parameters

<ParamField query="limit" type="integer" default="20">
  Number of submissions to return per page. Maximum `100`.
</ParamField>

<ParamField query="cursor" type="string">
  Pagination cursor from a previous response's `next_cursor`. Omit to start from the most recent submission.
</ParamField>

<ParamField query="created_after" type="string">
  ISO 8601 datetime. Only return submissions created after this timestamp, e.g. `2025-01-01T00:00:00Z`.
</ParamField>

<ParamField query="created_before" type="string">
  ISO 8601 datetime. Only return submissions created before this timestamp.
</ParamField>

### Response

<ResponseField name="data" type="object[]">
  Array of submission objects.

  <Expandable title="Submission object properties">
    <ResponseField name="id" type="string">
      Unique submission identifier, prefixed with `sub_`.
    </ResponseField>

    <ResponseField name="form_id" type="string">
      The ID of the form this submission belongs to.
    </ResponseField>

    <ResponseField name="data" type="object">
      Key-value map of field IDs to submitted values. The key is the field's `id` (e.g. `fld_a1B2c3D4`) and the value is whatever the respondent entered.
    </ResponseField>

    <ResponseField name="metadata" type="object">
      Contextual metadata captured at submission time.

      <Expandable title="Metadata properties">
        <ResponseField name="ip" type="string">
          IP address of the respondent.
        </ResponseField>

        <ResponseField name="user_agent" type="string">
          Browser user-agent string.
        </ResponseField>

        <ResponseField name="referrer" type="string">
          URL of the page the form was submitted from, if available.
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="submitted_at" type="string">
      ISO 8601 timestamp of when the submission was received.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="next_cursor" type="string">
  Cursor for the next page. `null` when you are on the last page.
</ResponseField>

<ResponseField name="has_more" type="boolean">
  `true` if there are more submissions beyond this page.
</ResponseField>

<CodeGroup>
  ```bash curl theme={null}
  curl --request GET \
    --url "https://api.formflows.ai/v1/forms/frm_8kQmP2xNvL/submissions?limit=25" \
    --header "Authorization: Bearer sk_live_your_api_key"
  ```

  ```python Python theme={null}
  import requests

  form_id = "frm_8kQmP2xNvL"
  all_submissions = []
  cursor = None

  while True:
      params = {"limit": 100}
      if cursor:
          params["cursor"] = cursor

      response = requests.get(
          f"https://api.formflows.ai/v1/forms/{form_id}/submissions",
          headers={"Authorization": "Bearer sk_live_your_api_key"},
          params=params,
      )

      result = response.json()
      all_submissions.extend(result["data"])

      if not result["has_more"]:
          break
      cursor = result["next_cursor"]

  print(f"Retrieved {len(all_submissions)} submissions.")
  ```
</CodeGroup>

**Example response:**

```json theme={null}
{
  "data": [
    {
      "id": "sub_7vHnM4rKpQ",
      "form_id": "frm_8kQmP2xNvL",
      "data": {
        "fld_a1B2c3D4": "Jane Smith",
        "fld_e5F6g7H8": "jane.smith@example.com",
        "fld_i9J0k1L2": ["Keynote", "Workshop A"]
      },
      "metadata": {
        "ip": "203.0.113.42",
        "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7)",
        "referrer": "https://www.example.com/register"
      },
      "submitted_at": "2025-01-15T14:32:00Z"
    },
    {
      "id": "sub_2bCdE5fGhI",
      "form_id": "frm_8kQmP2xNvL",
      "data": {
        "fld_a1B2c3D4": "Marcus Johnson",
        "fld_e5F6g7H8": "m.johnson@example.com",
        "fld_i9J0k1L2": ["Workshop B", "Networking Lunch"]
      },
      "metadata": {
        "ip": "198.51.100.17",
        "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)",
        "referrer": null
      },
      "submitted_at": "2025-01-15T13:18:00Z"
    }
  ],
  "next_cursor": "cur_eyJpZCI6InN1Yl8yIn0",
  "has_more": true
}
```

***

## Get a submission

`GET /forms/{id}/submissions/{submission_id}`

Returns a single submission by ID.

### Path parameters

<ParamField path="id" type="string" required>
  The form ID.
</ParamField>

<ParamField path="submission_id" type="string" required>
  The submission ID, e.g. `sub_7vHnM4rKpQ`.
</ParamField>

### Response

Returns the full submission object (same structure as in the list response above).

<CodeGroup>
  ```bash curl theme={null}
  curl --request GET \
    --url "https://api.formflows.ai/v1/forms/frm_8kQmP2xNvL/submissions/sub_7vHnM4rKpQ" \
    --header "Authorization: Bearer sk_live_your_api_key"
  ```

  ```python Python theme={null}
  import requests

  response = requests.get(
      "https://api.formflows.ai/v1/forms/frm_8kQmP2xNvL/submissions/sub_7vHnM4rKpQ",
      headers={"Authorization": "Bearer sk_live_your_api_key"},
  )

  submission = response.json()
  print(submission["data"])
  ```
</CodeGroup>

***

## Submit a form programmatically

`POST /forms/{id}/submissions`

Creates a new submission for a form without going through the public form URL. Use this to submit data on behalf of a user from your own backend.

<Note>
  This endpoint bypasses CAPTCHA and rate limiting that applies to the public form URL. Only call it from a trusted server-side environment — never from client-side code or a browser. Submissions created this way are tagged as `api` in the source field.
</Note>

### Path parameters

<ParamField path="id" type="string" required>
  The form ID to submit to.
</ParamField>

### Body parameters

<ParamField body="data" type="object" required>
  Key-value map of field IDs to values. Use the `id` of each field (visible in the form object) as the key. You must provide values for all `required` fields; optional fields can be omitted.
</ParamField>

### Response

Returns the created submission object with a `201 Created` status.

<CodeGroup>
  ```bash curl theme={null}
  curl --request POST \
    --url "https://api.formflows.ai/v1/forms/frm_8kQmP2xNvL/submissions" \
    --header "Authorization: Bearer sk_live_your_api_key" \
    --header "Content-Type: application/json" \
    --data '{
      "data": {
        "fld_a1B2c3D4": "Priya Patel",
        "fld_e5F6g7H8": "priya.patel@example.com",
        "fld_i9J0k1L2": ["Keynote", "Networking Lunch"]
      }
    }'
  ```

  ```python Python theme={null}
  import requests

  submission_data = {
      "data": {
          "fld_a1B2c3D4": "Priya Patel",
          "fld_e5F6g7H8": "priya.patel@example.com",
          "fld_i9J0k1L2": ["Keynote", "Networking Lunch"],
      }
  }

  response = requests.post(
      "https://api.formflows.ai/v1/forms/frm_8kQmP2xNvL/submissions",
      headers={"Authorization": "Bearer sk_live_your_api_key"},
      json=submission_data,
  )

  submission = response.json()
  print("Submission ID:", submission["id"])
  ```
</CodeGroup>

**Example response:**

```json theme={null}
{
  "id": "sub_9wXyZ0aB1C",
  "form_id": "frm_8kQmP2xNvL",
  "data": {
    "fld_a1B2c3D4": "Priya Patel",
    "fld_e5F6g7H8": "priya.patel@example.com",
    "fld_i9J0k1L2": ["Keynote", "Networking Lunch"]
  },
  "metadata": {
    "ip": null,
    "user_agent": null,
    "referrer": null,
    "source": "api"
  },
  "submitted_at": "2025-01-15T16:05:00Z"
}
```

***

## Delete a submission

`DELETE /forms/{id}/submissions/{submission_id}`

<Warning>
  Deleting a submission is permanent and cannot be undone. The submission data is removed from FormFlows.ai storage immediately and cannot be recovered.
</Warning>

### Path parameters

<ParamField path="id" type="string" required>
  The form ID.
</ParamField>

<ParamField path="submission_id" type="string" required>
  The submission ID to delete.
</ParamField>

### Response

Returns a `204 No Content` response on success, with no body.

<CodeGroup>
  ```bash curl theme={null}
  curl --request DELETE \
    --url "https://api.formflows.ai/v1/forms/frm_8kQmP2xNvL/submissions/sub_7vHnM4rKpQ" \
    --header "Authorization: Bearer sk_live_your_api_key"
  ```

  ```python Python theme={null}
  import requests

  response = requests.delete(
      "https://api.formflows.ai/v1/forms/frm_8kQmP2xNvL/submissions/sub_7vHnM4rKpQ",
      headers={"Authorization": "Bearer sk_live_your_api_key"},
  )

  if response.status_code == 204:
      print("Submission deleted.")
  ```
</CodeGroup>
