The FormSmarts API client allows you to quickly automate online form workflows with a simple and intuitive Python interface.

The FormSmarts API & Webhook Client

The FormSmarts API client allows you to automate form workflows with simple Python programs:

  • Take action immediately when a form is submitted with a webhook. You could for example use a webhook to add the information submitted to your CRM, update a customer profile or integrate the data to a Microsoft Word document and send it to a staff for review.
  • Create automations to search form entries (by date, email address or phone number) and add notes and tags or edit form entries with the FormSmarts API, and perform any action needed for your business.

The API & Webhook Client is a fully supported part of FormSmarts. If Python is not your things, feel free to reach out to FormSmarts Support, so we help you develop automations.

Here is a short code example that looks up forms submitted since May 5, 2025, and:

  1. Sends a copy of the form entry to a member of staff if the person checked a box asking to be contacted
  2. Adds the person's email to a mailing list if they agree to subscribe

from formsmarts_api import APIAuthenticator, FormEntry
auth = APIAuthenticator('my_acc_id', 'my_api_key')
entries = FormEntry.search_by_dates(auth, form_id='lqh', start_date='2025-05-05')
for e in entries:
    if e.fields_by_name('Contact me to discuss my needs')[0].value:
        e.add_tag('review')
        e.share('manager@example.com')
    if e.fields_by_name('Subscribe to the monthly newsletter')[0].value:
        mailing_list.add(e.fields_by_type('email')[0].value)

API Client for Python

The FormSmarts Webhook & API Client for Python allows FormSmarts members to search, access and edit form submissions and any attachments (uploaded files). It supports the following functions (check the API Reference section for a comprehensive description of each function):

API

  • API authentication
  • Search form submissions FormEntry.search()
  • Retrieve form responses submitted between two dates FormEntry.search_by_dates()
  • Get an individual form submission FormEntry.fetch()
  • Share a form submission FormEntry.share()
  • Download an individual form submission as a PDF FormEntry.download_pdf()
  • Download a form attachment Upload.download()
  • Submit a form FormEntry.submit()
  • Upload a form attachment Upload.upload()
  • Replace a form attachment Upload.replace()
  • Amend a form submission Field.value = 'new value'
  • List tags and system tags FormEntry.tags(), FormEntry.system_tags()
  • Get the reference number of a form entry FormEntry.reference_number
  • Find the date & time a form was submitted FormEntry.date_submitted
  • Get the ID of the form FormEntry.form_id
  • Get the name of the form FormEntry.form_name
  • Access the submission context of a form entry FormEntry.context
  • Get details of the payment associated with of a form entry FormEntry.payment
  • Add a tag to form response FormEntry.add_tag()
  • Iterate over input fields FormEntry.fields
  • Retrieve input fields by type FormEntry.fields_by_type['email']
  • Lookup input fields by name FormEntry.fields_by_name['Address']
  • Access input fields by Field ID FormEntry.field_by_id[12345]
  • Get the value of an input field Field.value
  • Get the name of a field Field.name
  • Get the datatype of a field Field.type
  • Get the ID of a field Field.id
  • Pre-populate a form and generate a pre-filled form URL with the PreFilledForm class

Webhook

  • Authenticate a webhook request WebhookAuthenticator.verify_request()
  • Create a FormEntry object from a webhook callback FormEntry.create()
  • Access all properties of the form entry with the FormEntry object (same as the API)
  • Get the amount due associated with the form entry WebhookEntry.amount_due

API Client for Node.JS

We maintain a basic Node.js client that currently only covers API and webhook authentication.

Getting Started

Installation

The client is available as a Python package. Download it and place it with your Python code.

# Import the Python package
import formsmarts_api 

Authentication

The client uses JWT tokens for request authentication, which are generated using your Account ID and API Key.

  1. Obtain Credentials: Your Account ID and secret API Key can be found in the FormSmarts Account settings (Account Overview and Security Settings sections).
  2. Initialize Authenticator: You must first create an instance of the APIAuthenticator class using your credentials.

Example Authentication Setup:

from formsmarts_api import APIAuthenticator

# It is recommended to load credentials from a secure configuration file or environment variables
FORMSMARTS_ACCOUNT_ID = 'FSA-999999'
FORMSMARTS_API_KEY = 'TqE35BBzxfmxC74YQ4jQCPFx1oKvFhECOfWrbTh8fVMG6viZWiTfvh4dOZSSK71v'

auth = APIAuthenticator(FORMSMARTS_ACCOUNT_ID, FORMSMARTS_API_KEY)

Python API Reference

The primary class for interacting with form submissions is FormEntry. The Upload class handles file attachments.

FormEntry Class

This class represents a single form submission and provides methods for searching, retrieval, submission, and manipulation of form data.

Method/Property Description Parameters Returns
FormEntry.fetch() Gets an individual form submission by its Reference Number. api_authenticator: APIAuthenticator object
ref_num: reference number of the form entry
FormEntry object
FormEntry.download_pdf() Downloads a form submission as a PDF document. api_authenticator: APIAuthenticator object
ref_num: reference number of the form submission
io_stream: binary file-like object
timezone: timezone of dates in the document, e.g. "Europe/London" (optional, "UTC" by default)
None
FormEntry.search() Searches form submissions based on criteria. api_authenticator: APIAuthenticator object
query: email address, phone number, ID or the 'latest' keyword
form_id: The ID of the form (if a form's URL is https://f8s.co/xyz, its ID is "xyz")
tags: tag or list of tags (optional filter)
system_tags: system tag or list of system tags (optional filter)
List of FormEntry objects
FormEntry.search_by_dates() Retrieves form responses submitted within a date range. api_authenticator: APIAuthenticator object
form_id: The ID of the form
start_date: date object or ISO string YYYY-MM-DD
end_date: date object or ISO string YYYY-MM-DD (optional)
timezone: timezone of dates in the FormEntry objects returned, e.g. "Europe/London" (optional, "UTC" by default)
List of FormEntry objects
FormEntry.fetch_batch() Returns form entries from a list of reference numbers. api_authenticator: APIAuthenticator object
form_id: The ID of the form
reference_numbers: a list of Reference Numbers
timezone: timezone of dates in the FormEntry objects returned, e.g. "Europe/London" (optional, "UTC" by default)
List of FormEntry objects
FormEntry.submit() Submits a new entry to a specified form. api_authenticator: APIAuthenticator object
form_id: The ID of the form
fields: A dictionary mapping Field IDs (as keys) to values (example) or a list of Field objects.
Reference Number (string)
FormEntry.share() Shares the form submission via email (restrictions apply) emails: list of email addresses None
FormEntry.add_tag() Adds a custom tag to the form response. tag_name (string) None
FormEntry.reference_number Property: The unique reference number of the entry. N/A String
FormEntry.date_submitted Property: The date and time the form was submitted. N/A datetime object
FormEntry.form_id Property: ID of the form. N/A String
FormEntry.form_name Property: Name of the form. N/A String
FormEntry.tags Property: Tags associated with the form entry. N/A List of strings
FormEntry.system_tags Property: System tags associated with the form entry. N/A List of strings
FormEntry.fields Property: An iterable object containing all input fields. N/A List of Field objects
FormEntry.fields_by_name[] Property: Looks up input fields by the field's name. Field Name (string) List of Field objects
FormEntry.field_by_id[] Property: Accesses an input field directly by its ID. Field ID (integer) Field object
FormEntry.context Property: Form submission context. N/A dict {'label': '', 'value': ''}
FormEntry.payment Property: Payment associated with this form submission. N/A dict {'amount': Decimal('0.00'), 'currency': 'USD', 'transaction_id': '', processor_name=''}

Form Class

The Form class encapsulates the structure of a form and its associated input fields and metadata.

Method/Property Description Parameters Returns
Form(api_authenticator, form_id) Constructor: Initializes a new instance. api_authenticator: APIAuthenticator object
form_id: The ID of the form (string)
Form object
Form.form_id Property: The ID of the form. N/A String
Form.fields Property: Returns a list of fields in the order they appear on the form. N/A List of Field objects
Form.field_by_id() Look up a field by its Field ID. field_id: The unique ID of the field (integer) Field object
Form.fields_by_type() Look up input fields by datatype (e.g., 'email', 'upload'). field_type: The datatype to search for (string) List of Field objects
Form.fields_by_name() Look up input fields by name. field_name: The name of the field (string) List of Field objects

Example


from formsmarts_api import APIAuthenticator, FormEntry, Form
from config import FORMSMARTS_ACCOUNT_ID, FORMSMARTS_API_KEY

FIELD_VALUES = {
    "First Name": "Jane",
    "Last Name": "Doe",
    "Phone Number": "(999) 999-9999",
    "Preferred Date": "2021-08-23",
}

class FormSubmitter:

    def __init__(self, form_id):
        self.form_id = form_id
        self.auth = APIAuthenticator(FORMSMARTS_ACCOUNT_ID, FORMSMARTS_API_KEY)
        self.form = Form(self.auth, form_id)  # Load the form structure

    def submit_form(self, field_values):
        fields = []
        for name, val in field_values.items():
            field = self.form.fields_by_name(name)[0]
            field.set_value(val)
            fields.append(field)
        return FormEntry.submit(self.auth, self.form_id, fields)

FormSubmitter('24yc').submit_form(FIELD_VALUES)

Field Class

The Field class provides access the properties of input fields and allows you to edit a field's value for the corresponding form entry. Use FormEntry.fields, FormEntry.fields_by_name[] or FormEntry.field_by_id[] to list the fields of a form entry.

Method Description Parameters Returns
Field.name Property: The field's name. N/A String
Field.id Property: The field's unique ID. N/A Integer
Field.value Property: The field's vale. N/A Depends on the field's datatype
Field.type Property: The field's datatype. N/A String
Field.value = 'new value' Property: Amends the value of a field for a specific form entry (e.g., entry.field_by_id[12345].value = 'updated') N/A None
Field.set_value() Sets the value attribute of the Field object. This is different from: Field.value = 'new value' above. value: a new value None

Upload Class (File Attachments)

Use the Upload class to handle files uploaded.

Method Description Parameters Returns
Upload.upload() Uploads a file attachment. api_authenticator: APIAuthenticator object
form_id: Form ID
field_id ID of the (upload) field
io_stream: file-like object
filename: name of the file
content_type: MIME Content Type, e.g. 'image/png'
Upload ID (string)
Upload.download() Downloads a form attachment. io_stream: file-like object None
Upload.replace() Replaces an existing form attachment. io_stream: file-like object
filename: name of the new file
content_type: MIME Content Type, e.g. 'image/png'
None
Upload.filename Property: The original filename. N/A String
Upload.upload_id Property: The unique ID of the file. N/A String
Upload.url Property: The URL to access the file (authentication needed). N/A String
Upload.presigned_url Property: Presigned URL valid 5 min. Only available in webhooks callbacks. N/A String

Form Submission Example

This example demonstrates how to upload a file and then submit a form containing an upload field.

import config
import os.path
from formsmarts_api import APIAuthenticator, APIEntry, Upload, APIRequestError

# Setup Authentication and Form IDs
FORM_ID = 'lqh'
UPLOAD_FIELD_ID = 122621 # ID of the file upload field on your form
auth = APIAuthenticator(config.FORMSMARTS_ACCOUNT_ID, config.FORMSMARTS_API_KEY)
fields = {
    122619: 'Jane Doe',
    122620: 'blackhole@formsmarts.net',
    UPLOAD_FIELD_ID: '', # Placeholder for the Upload ID
    123744: "Hello,\nThanks for playing.",
}

def submit_with_upload(path, filename):

    # STEP 1: Upload the file
    print(f"Uploading {filename}...")
    file = open(os.path.join(path, filename), 'rb')

    try:
        upload_id = Upload.upload(
            auth,
            form_id=FORM_ID,
            field_id=UPLOAD_FIELD_ID,
            io_stream=file,
            filename=filename,
            content_type='image/png' # Set the correct content type
        )
        print(f'Picture uploaded successfully as Upload ID: {upload_id}')

        # Set the upload field value to the returned Upload ID
        fields[UPLOAD_FIELD_ID] = upload_id

        # STEP 2: Submit the form
        ref_num = APIEntry.submit(auth, FORM_ID, fields)
        print(f'Form submitted successfully. Reference Number: {ref_num}')

    except APIRequestError as err:
        print(f"An API error occurred: {err}")
    finally:
        file.close()

# Example usage (assuming 'test-image.png' is in '/tmp')
# submit_with_upload('/tmp', 'test-image.png')

PreFilledForm Class

The PreFilledForm class allows you to pre-populate a form and generate a pre-filled form URL. It handles the retrieval of form field details via the API and automatically calculates the digital signature required to secure the pre-filled data.

Constructor

PreFilledForm(api_authenticator, form_id, prefill_key, hash_algo='sha256')

Initializes a new instance. Requires an authentication APIAuthenticator object to fetch field metadata, the ID of the form, and the account's Pre-fill Key for signing.

  • Create an APIAuthenticator object with your FormSmarts Account ID and API Key
  • The ID of a form is the last part of its URL. For example, if the URL of a form is: https://f8s.co/xyz, its ID is "xyz"
  • Get your secret Pre-fill Key in the Security Settings of your account.
Member Description Parameters Returns
fields_by_name(field_name) Look up input fields by their name (or question text) as it appears on the form. field_name (str) list of Field objects
field_by_id(field_id) Look up a single input field using its unique Field ID. field_id (str) Field object
pre_fill(field, value, readonly=False) Pre-populates a specific field object with a value. Set readonly=True to prevent the user from changing this value on the form. field (Field object)
value (str or object convertible to a str)
readonly (bool)
None
get_url() Generates and returns the pre-filled form URL. None str

Example


import config
from formsmarts_api import APIAuthenticator, PreFilledForm

# Initialize authentication
# Replace with your actual Account ID, API Key, and Pre-fill Key
# Do not hardcode your secret API & Pre-Fill keys, retrieve them from environment variables, config file or key store.
auth = APIAuthenticator(config.YOUR_ACCOUNT_ID, config.YOUR_API_KEY)

# Initialize the PreFilledForm for the demo form: https://f8s.co/2036, Form ID '2036'
pf = PreFilledForm(auth, '2036', config.YOUR_PREFILL_KEY)

# Define the data to populate, keys are the names of the fields on form: https://f8s.co/2036
# Note how we prevent users from modifying the first three fields by making them "readonly".
data = {
    'Client ID': {'value': 789034, 'readonly': True},
    'First Name': {'value': 'Jane', 'readonly': True},
    'last Name': {'value': 'Doe', 'readonly': True},
    'Email': {'value': 'blackhole@formsmarts.net'}
}

# Lookup fields and pre-fill them
for name, prefill in data.items():
    # fields_by_name() returns a list because names might not be unique
    fields = pf.fields_by_name(name)
    if fields:
        # We populate the first matching field found
        pf.pre_fill(fields[0], prefill['value'], readonly=prefill.get('readonly'))

# Generate the pre-filled form URL
url = pf.get_url()
print(f"Pre-filled form link: {url}")

Webhook Reference

The client includes functionality to authenticate and process incoming webhook requests from FormSmarts.

WebhookAuthenticator Class

The client uses JWT tokens to authenticate webhook callbacks and verify that the requests were indeed submitted by FormSmarts. The tokens are generated using your Webhook Key.

  1. Obtain Credentials: You can find your secret Webhook Key in the Security Settings section of your FormSmarts Account.
  2. Initialize Authenticator: You must first create an instance of the WebhookAuthenticator class using your credentials.

Example Authentication Setup:

from formsmarts_api import WebhookAuthenticator

# It is recommended to load credentials from a secure configuration file or environment variables
FORMSMARTS_WEBHOOK_KEY = 'TqE35BBzxfmxC74YQ4jQCPFx1oKvFhECOfWrbTh8fVMG6viZWiTfvh4dOZSSK71v'
auth = formsmarts_api.WebhookAuthenticator(FORMSMARTS_WEBHOOK_KEY)
Method Description Parameters Returns
WebhookAuthenticator() Constructor webhook_key: Your secret Webhook Key (from the Security Settings of your account) WebhookAuthenticator object
WebhookAuthenticator.verify_request() Authenticates an incoming webhook request to ensure it originated from FormSmarts. authorization_header The value of the Authorization header from the incoming HTTP request Boolean (True if valid)

FormEntry Class

The FormEntry class can be instantiated directly from a webhook callback payload.

Method Description Parameters Returns
FormEntry.create() Creates a FormEntry object from the payload of a webhook callback.
Always verify that the request originates from FormSmarts with WebhookAuthenticator.verify_request() before using FormEntry.create().
webhook_payload: Body of the webhook request FormEntry object

Webhook Example

The code below shows how to write a simple webhook callback in Python with the FormSmarts API & Webhook Client.

Note how we:

  1. Verify that the callback was submitted by FormSmarts from the signature in the request headers with WebhookAuthenticator.verify_request()
  2. Create a FormEntry object from the body of the request with FormEntry.create()
  3. Get the picture upload field with self._entry.fields_by_type('upload')[0]
  4. Download the picture and save it to a file with pic.download()


import formsmarts_api
import json
import config

logger = logging.getLogger()

class WebhookExample:

    def __init__(self, event):
        self._event = event
        self._api_auth = formsmarts_api.APIAuthenticator(
            config.FORMSMARTS_ACCOUNT_ID, config.FORMSMARTS_API_KEY
        )
        self._wh_auth = formsmarts_api.WebhookAuthenticator(config.FORMSMARTS_WEBHOOK_KEY)
        self._entry = None

    def process_entry(self):
        try:
            # Verify request is from FormSmarts
            if self._wh_auth.verify_request(self._event['headers']['authorization']):
                # Create a FormEntry object from the webhook message
                self._entry = formsmarts_api.FormEntry.create(
                    json.loads(self._event['body']),
                    api_authenticator=self._api_auth
                )
                self.save_picture()
            except formsmarts_api.APIRequestError as err:
                logger.warning(err)

    def save_picture(self):
        # Lookup up the first upload field and download a copy of the picture
        pic = self._entry.fields_by_type('upload')[0]
        pic.download(open(
            f'/Downloads/{self._entry.reference_number}-{pic.filename}', 'wb'
            ))

def lambda_handler(event, context):
    WebhookExample(event).process_entry()

Webhook Use Cases & Examples

Frequent uses of webhooks include:

  • Sending notifications by SMS, to Microsoft Teams or Slack based on preset conditions
  • Generating Word or PDF documents
  • Saving the information submitted to a local database
  • Subscribing/unsubscribing an email address from a mailing list