Product Demos Pricing Docs Log in Start free →

HomeDocsSubmissions API

Submissions API

Read the responses your forms collect. Submissions are created by respondents through the hosted form or an embed — the API is read-only for them, so your data stays exactly as it was submitted.

All endpoints require a bearer token. You can only read submissions of forms in the token's workspace.

The submission object

{
    "id": 9812,
    "form_id": 42,
    "answers": {
        "Name": "Jane Smith",
        "Email": "[email protected]",
        "Topic": "Sales",
        "Interests": ["Product news", "Webinars"],
        "Message": "I'd like a demo.",
        "Attachment": {
            "path": "submissions/website-contact-form-k3j9xa/brief.pdf",
            "name": "brief.pdf",
            "size": 48211,
            "mime": "application/pdf"
        },
        "source": "website"
    },
    "metadata": {
        "ip": "203.0.113.7",
        "user_agent": "Mozilla/5.0 …",
        "referrer": "https://example.com/pricing",
        "source_url": "https://example.com"
    },
    "read_at": null,
    "created_at": "2026-09-04T09:41:12+00:00"
}
Field Type Description
id integer Submission ID.
form_id integer The form it belongs to.
answers object One key per answered field, keyed by the field's label at the time of submission. Fields hidden by conditional logic are omitted.
answers.<label> string Text, email, phone, number, dropdown, radio, date (YYYY-MM-DD) and hidden fields.
answers.<label> array of strings checkbox fields — the selected options.
answers.<label> object file fields — path (storage path), name (original filename), size (bytes) and mime. Download files from the submissions page in your dashboard.
metadata.ip string Respondent's IP address.
metadata.user_agent string Respondent's browser user agent.
metadata.referrer string or null The page the respondent came from (Referer header).
metadata.source_url string or null Origin of the site the form was embedded on.
read_at ISO 8601 datetime or null When the submission was marked read in the dashboard. null means unread.
created_at ISO 8601 datetime When it was submitted, in UTC.

List submissions

GET /forms/{form}/submissions
Query parameter Type Description
per_page integer 1–100 Submissions per page. Default 25.
cursor string The meta.next_cursor value from the previous page. Omit for the first page.
unread 1 Only submissions that have not been marked read.
since ISO 8601 date or datetime Only submissions created at or after this moment, e.g. 2026-09-01 or 2026-09-01T00:00:00Z. Handy for incremental syncs — store the newest created_at you have seen and pass it next time.

Submissions are ordered newest first and paginated with a cursor, so paging is stable even while new submissions arrive.

curl "https://rapidform.com/api/v1/forms/42/submissions?per_page=50&since=2026-09-01" \
  -H "Authorization: Bearer $RAPIDFORM_API_KEY"
{
    "data": [ { "id": 9812, "form_id": 42, "answers": { "…": "…" }, "…": "…" } ],
    "links": { "first": null, "last": null, "prev": null, "next": "…?per_page=50&cursor=eyJpZCI6OTc2MywiX3BvaW50c1RvTmV4dEl0ZW1zIjp0cnVlfQ" },
    "meta": {
        "path": "https://rapidform.com/api/v1/forms/42/submissions",
        "per_page": 50,
        "next_cursor": "eyJpZCI6OTc2MywiX3BvaW50c1RvTmV4dEl0ZW1zIjp0cnVlfQ",
        "prev_cursor": null
    }
}

To fetch everything, keep requesting with cursor set to meta.next_cursor until it is null:

CURSOR=""
while :; do
  PAGE=$(curl -s "https://rapidform.com/api/v1/forms/42/submissions?per_page=100&cursor=$CURSOR" \
    -H "Authorization: Bearer $RAPIDFORM_API_KEY")
  echo "$PAGE" | jq -c '.data[]'
  CURSOR=$(echo "$PAGE" | jq -r '.meta.next_cursor // empty')
  [ -z "$CURSOR" ] && break
done

Responds 404 if the form is not in this key's workspace.

Get a submission

GET /submissions/{submission}

Returns {"data": { …submission object… }}. Responds 404 if the submission belongs to a form outside this key's workspace.

curl https://rapidform.com/api/v1/submissions/9812 \
  -H "Authorization: Bearer $RAPIDFORM_API_KEY"

Receiving submissions in real time

Polling with since works well for syncs, but if you want each submission pushed to you the moment it arrives, add a webhook to the form.