Excel reports allow you to export form responses submitted between two dates as a spreadsheet. The Form Responses by Dates API returns the same results, but provides automated, programmatic access and sends data back in JSON format.

The Form Responses by Dates API

To look up1 form entries submitted between two dates, insert the form's ID into the URL and submit a GET request:

API Endpoint
https://formsmarts.com/api/v1/forms/Form_ID/entries/by/dates
HTTP Method
GET
ParameterDescriptionNotes
start_date Start date in ISO 8601 format, e.g. 2020-12-30 Required
end_date End date in ISO 8601 format, e.g. 2020-12-31 Optional, defaults to the current date if omitted
structure Set to true to include the form structure (list of input fields with their name, ID and data type) in the API response. Optional, true or false, defaults to false.
presigned_urls Set to true to include pre-signed URLs in the API response so you can automatically retrieve the form uploads and eSignatures associated with a form submission. Pre-signed URLs are only valid for a few minutes. Optional, true or false, defaults to false.
tags Set to true to include the tags and system tags of each form response in the API response. Optional, true or false, defaults to false.
timezone Timezone used for dates in the API response, for example America/Los_Angeles. Timezones are listed here. Also defines the timezone of the start_date and end_date parameters. Optional. If missing, we use the timezone of your account or UTC if no timezone is set.
limit The maximum number of form responses to return. See Pagination below. Optional, 100 by default, 250 maximum.
offset An offset to return partial results, for example 100 returns form responses 101 and above. See Pagination below. Optional, 0 by default, 10,000 maximum.
The ID of a form is the alphanumeric string in its FormSmarts.com URL. For example, if a form's URL is https://formsmarts.com/form/2xyz, its Form ID is 2xyz.

API Response

If the request is successful, the API returns an HTTP 200 status and a JSON object with the form submissions.

  • If the structure parameter is true, the API response has a fields attribute. Unlike the Form Response API, this endpoint doesn't return a form attribute: you already know the ID of the form, since it's part of the URL.
  • A list of form responses is accessible at api_response["entries"]. Entries are returned in the order they were submitted.
  • If the form entry at index i has a form context value, it is included in api_response["entries"][i]["context"]["value"]
  • If the form submission involved a payment, the amount, currency, processor name and transaction ID of the payment are available in a api_response["entries"][i]["payment"] object.
  • If the tags parameter is true, the tags and system tags of each form response are returned as two lists in the entry's metadata: api_response["entries"][i]["metadata"]["user_tags"] and api_response["entries"][i]["metadata"]["system_tags"]
  • As shown below, the value of upload and signature fields are JSON object. All other values are scalars.

Example

This is the API response for this form demo:

{
  "fields": [
    {
      "name": "Full Name",
      "id": 122619,
      "type": "name"
    },
    {
      "name": "Email",
      "id": 122620,
      "type": "email"
    },
    {
      "name": "Upload Your Picture",
      "id": 122621,
      "type": "upload"
    },
    {
      "name": "Comments",
      "id": 123744,
      "type": "text"
    }
  ],
  "entries": [
    {
      "entry": [
        "Nicky Smith",
        "nicky@example.com",
        {
          "type": "upload",
          "attachment_id": "fbfn",
          "filename": "Screen Shot 2022-04-27 at 2.43.32 PM.png"
        },
        ""
      ],
      "metadata": {
        "reference_number": "AE9IG131SWA4ZD90R454WWK6N",
        "date_submitted": "2022-05-01T15:43:08-07:00",
        "user_tags": ["reviewed"],
        "system_tags": []
      }
    },
    {
      "entry": [
        "Mag Tan",
        "mag.tan@example.org",
        {
          "type": "upload",
          "attachment_id": "fc0p",
          "filename": "mag-picture-1.jpg"
        },
        ""
      ],
      "metadata": {
        "reference_number": "1WWTZYYKM4ZSHYS5CZZC6BIED",
        "date_submitted": "2022-05-03T01:39:48-07:00",
        "user_tags": [],
        "system_tags": ["api submitted"]
      }
    }
  ]
}

The user_tags and system_tags metadata items above are only returned if the request has tags=true.

If the request fails, the API returns a non-success HTTP status with a JSON object specifying the error.

Pagination

The API returns at most 250 form responses per request (100 by default). To retrieve every entry submitted over a date range, request successive pages with the offset parameter, increasing it by the number of entries returned until the API returns fewer entries than the limit requested.

The API & Webhook Client handles pagination for you: FormEntry.search_by_dates() returns a generator that fetches the next page as you iterate over the results.

Authentication

FormSmarts verifies API requests with a JWT token in the Authorization header. You can sign requests with the FormSmarts API Client or a JWT library in your favorite programming language. You'll need to know your FormSmarts Account ID and secret FormSmarts API Key.

You'll find your Account ID in the Account Overview section of your account and your API Key in the Security Settings.

Python Example

The easiest way to use the Form Responses by Dates API is with the API & Webhook Client, which provides a Python interface to FormSmarts services. Install it with pip:

pip install formsmarts

The example below retrieves the form entries submitted within the past seven days and downloads the pictures uploaded on the form. Using the API Client, we can easily:

  • Retrieve and iterate over the form responses submitted in the last seven days with: FormEntry.search_by_dates(), which pages through results transparently
  • Get the picture upload field with: pic = entry.fields_by_type('upload')[0]
  • Download the picture with: pic.download()

Credentials are read from environment variables — never hard-code them in your source.


import os.path
from datetime import date, timedelta
from formsmarts import APIAuthenticator, FormEntry, APIRequestError

auth = APIAuthenticator(os.environ['FS_ACCOUNT_ID'], os.environ['FS_API_KEY'])

def download_pictures(start, end):
    try:
        entries = FormEntry.search_by_dates(
            auth, form_id='lqh', start_date=start, end_date=end,
            timezone='America/Los_Angeles', return_tags=True
        )
        for entry in entries:
            if 'processed' in entry.tags:
                continue  # Already downloaded on an earlier run
            get_picture(entry)
            entry.add_tag('processed')
    except APIRequestError as err:
        print(f'Error {err.status}: {err}')

def get_picture(entry):
    pic = entry.fields_by_type('upload')[0]  # Picture is the first upload field
    pic.download(
        os.path.join('/Users/test/Downloads', f'{entry.reference_number}-{pic.filename}')
    )

today = date.today()
download_pictures(start=today - timedelta(days=7), end=today)

return_tags=True returns the tags and system tags of each form response with the entry, so reading entry.tags in the loop above doesn't require an extra API request per entry.

If you prefer to call the API directly with an HTTP library or another programming language, here is an equivalent request:


import os
import requests
from formsmarts import APIAuthenticator

API_URL = 'https://formsmarts.com/api/v1/forms/lqh/entries/by/dates'

auth = APIAuthenticator(os.environ['FS_ACCOUNT_ID'], os.environ['FS_API_KEY'])

resp = requests.get(
    API_URL,
    params={'start_date': '2026-09-01', 'end_date': '2026-09-07', 'structure': 'true',
            'tags': 'true', 'limit': 250, 'offset': 0},
    headers={APIAuthenticator.AUTH_HEADER: auth.get_authorization_header()}
)
if resp.status_code == 200:
    print(resp.json())
else:
    print(f'Error {resp.status_code}: {resp.text}')

Node.js Example

The Form Submission API has a Node.js example.


  1. Not available with Business Starter and Plus accounts.