How to Export Non-Mapped HubSpot Form Submissions (The Data You Can't Get From Contacts API)
Use the Form Integrations Submissions API to retrieve unmapped form fields and export to CSV

📚 Get Practical Development Guides
Join developers getting comprehensive guides, code examples, optimization tips, and time-saving prompts to accelerate their development workflow.
I ran into a frustrating problem last week while extracting form data from HubSpot for a client. They were using Elementor forms that submitted to HubSpot, but several form fields weren't mapped to contact properties. When I pulled contact data using the Contacts API, those unmapped fields were completely missing.
The HubSpot documentation doesn't address this scenario directly. Every article and API reference focuses on contact properties—not the raw submission data that sits in form submissions but never makes it to the contact record. After hours of testing different endpoints and reading through forum threads, I found the workaround and built a tool to solve it permanently.
The Problem With Non-Mapped Form Fields
Here's the specific issue: when you have a non-HubSpot form (Elementor, custom HTML forms, etc.) submitting to HubSpot, you can collect any field data you want. But if those fields don't map to existing contact properties, that data only exists in the form submission detail view. You can see it in the HubSpot UI when you click into individual submissions, but there's no straightforward way to export it in bulk.
The Contacts API endpoint returns contact properties. If your form field doesn't map to a contact property, that data never becomes part of the contact record. The standard Forms API gives you form definitions, but not submission details. I spent significant time searching for an export method in the HubSpot documentation—nothing directly addressed accessing these non-mapped submission fields programmatically.
The Solution: Form Integrations API
The endpoint that actually works is the form integrations submissions API. This is what finally retrieved the complete submission data:
curl --request GET \
--url 'https://api.hubapi.com/form-integrations/v1/submissions/forms/{form_guid}?limit=50' \
--header 'Authorization: Bearer YOUR_API_TOKEN'
The critical detail is using the correct form GUID. You can find this in the HubSpot URL when viewing submissions:
https://app.hubspot.com/submissions/{portal_id}/form/{form_guid}/submissions/{submission_id}
The form_guid
is the identifier between /form/
and /submissions/
. This endpoint returns all submission data including fields that were never mapped to contact properties. Each submission includes a values
array with every field that was submitted, regardless of mapping status.
Building the Export Tool
Once I confirmed this endpoint worked, I built a Python script to automate the entire export process. The tool fetches all forms from your HubSpot account, retrieves every submission using the form integrations endpoint, and exports each form to a separate CSV file.
The key implementation handles pagination automatically since HubSpot uses cursor-based pagination with an after
parameter:
# File: main.py
def get_all_form_submissions(form_guid):
"""Get ALL submissions for a form with pagination"""
all_submissions = []
url = f"{BASE_URL}/form-integrations/v1/submissions/forms/{form_guid}"
params = {"limit": 50}
page = 1
while True:
response = requests.get(url, headers=HEADERS, params=params)
response.raise_for_status()
data = response.json()
submissions = data.get("results", [])
all_submissions.extend(submissions)
# Check for next page
paging = data.get("paging", {})
next_info = paging.get("next", {})
if next_info and "after" in next_info:
params["after"] = next_info["after"]
page += 1
time.sleep(0.2)
else:
break
return all_submissions
The submission data extraction pulls every field dynamically from the values
array:
# File: main.py
def extract_submission_data(submission):
"""Extract ALL fields dynamically"""
data = {
"submission_id": submission.get("conversionId"),
"submitted_at": submission.get("submittedAt"),
"page_url": submission.get("pageUrl")
}
for value_obj in submission.get("values", []):
field_name = value_obj.get("name")
field_value = value_obj.get("value")
if field_name in data:
data[field_name] = f"{data[field_name]}; {field_value}"
else:
data[field_name] = field_value
return data
This approach captures everything submitted through the form, including fields that don't exist as contact properties in HubSpot.
Handling Forms That Don't Appear in the API
Another issue I encountered: some forms don't show up in the Forms API response at all. This happened with the Elementor forms that were submitting directly to HubSpot through the forms endpoint. The form GUID exists and submissions are recorded, but the form itself isn't returned by /forms/v2/forms
.
The workaround is manually adding these forms to the script:
# File: main.py
ADDITIONAL_FORMS = [
{
"guid": "f5d75534-81cf-4daa-a8e2-ec847fd43704",
"name": "#launch_contactform_id .elementor-form"
},
{
"guid": "2dc57586-08ae-4d19-a88b-526eb174a593",
"name": "#vendorcontactform .elementor-form"
}
]
The script combines forms from the API response with these manually specified forms, ensuring you can export submissions for any form where you have the GUID.
Using the Tool
I've released this as an open-source project. Setup takes about two minutes:
git clone https://github.com/matija2209/hs-forms-submissions-exporter.git
cd hs-forms-submissions-exporter
pip install -r requirements.txt
cp .env.example .env
Add your HubSpot API token to the .env
file. Generate a token in HubSpot under Integrations → Private Apps with the forms read scope enabled:
HUBSPOT_API_TOKEN=your_actual_token_here
Run the export:
python main.py
The script fetches all forms, retrieves every submission with pagination handling, and saves separate CSV files in the exports
directory. Each CSV includes all submission fields—both mapped and non-mapped to contact properties.
Why This Matters
If you're dealing with custom forms, Elementor forms, or any submission source where fields don't perfectly align with HubSpot contact properties, you need access to raw submission data. The Contacts API won't give you this. The form integrations submissions endpoint is the only way I found to programmatically access this data in bulk.
This solved a critical gap in my workflow where client reporting required the full submission dataset, not just the subset that made it into contact records. The tool now runs on a schedule for several clients who need regular exports of their complete form data.
The repository is available at github.com/matija2209/hs-forms-submissions-exporter. If you've struggled with this same problem or find other use cases for the tool, let me know in the comments.
Thanks, Matija