Submissions API
Programmatically list, fetch, export, and delete form submissions via the FiraForm API
Submissions API
The Submissions API lets you programmatically access, export, and manage the submissions collected by your forms. It is designed for building dashboards, syncing data to external systems, and automating workflows beyond what webhooks cover.
Base URL
https://a.firaform.com
All endpoints below are relative to this base URL.
Authentication
Every Submissions API endpoint requires a Bearer token sent in the Authorization header:
Authorization: Bearer {token}
Getting a Token
You can obtain an API token in two ways:
- From the web dashboard — Go to Profile → API Tokens at
/profile/tokensand create a new token. This is the recommended way for most users. - Via the API — Send a
POST /api/loginrequest with your credentials to receive a token programmatically.
Login Request
curl -X POST https://a.firaform.com/api/login \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"email": "[email protected]",
"password": "your-password"
}'
Request Body (JSON):
{
"email": "[email protected]",
"password": "your-password"
}
| Field | Required | Description |
|---|---|---|
email | Yes | The email address of your FiraForm account |
password | Yes | Your account password |
Login Response
Status Code: 200 OK
{
"token": "1|abcdef1234567890abcdefghijklmnopqrstuvwxyz",
"token_type": "Bearer"
}
Use the returned token value as the Bearer token in the Authorization header for all subsequent requests.
Invalid Credentials
Status Code: 401 Unauthorized
{
"message": "Invalid credentials."
}
Managing Tokens
API tokens are managed from the web user panel under Profile → API Tokens (/profile/tokens). From there you can:
- Create new tokens
- Name tokens (e.g. “CI export script”, “Analytics sync”)
- Revoke tokens when they are no longer needed
- Rotate tokens if you suspect a compromise
Treat tokens like passwords. Store them in environment variables or a secrets manager — never commit them to source control or expose them in client-side code.
Authentication Header Example
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://a.firaform.com/api/forms/{form_uuid}/submissions
Missing or Invalid Token
Status Code: 401 Unauthorized
{
"message": "Unauthenticated."
}
Endpoints
List Submissions
GET /api/forms/{form_uuid}/submissions
Returns a paginated list of submissions for a form.
Query Parameters
| Parameter | Required | Description |
|---|---|---|
spam_status | No | Filter by spam classification: clean, spam, pending, or suspicious |
per_page | No | Items per page (1–100). Default is 15 |
page | No | Page number. Default is 1 |
Example Request
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
"https://a.firaform.com/api/forms/{form_uuid}/submissions?spam_status=clean&per_page=25&page=1"
Example Response
Status Code: 200 OK
{
"data": [
{
"id": 123456,
"form_uuid": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"name": "John Doe",
"email": "[email protected]",
"message": "Hello!"
},
"spam_status": "clean",
"spam_score": 5,
"created_at": "2026-01-21T14:30:00Z",
"files": []
}
],
"meta": {
"current_page": 1,
"last_page": 4,
"per_page": 25,
"total": 92
}
}
The response is a Laravel-style paginator. Use meta.last_page to know when to stop paginating.
Get Single Submission
GET /api/forms/{form_uuid}/submissions/{id}
Returns a single submission with its full form data and uploaded files.
Example Request
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://a.firaform.com/api/forms/{form_uuid}/submissions/123456
Example Response
Status Code: 200 OK
{
"data": {
"id": 123456,
"form_uuid": "550e8400-e29b-41d4-a716-446655440000",
"data": {
"name": "John Doe",
"email": "[email protected]",
"message": "Hello!"
},
"spam_status": "clean",
"spam_score": 5,
"created_at": "2026-01-21T14:30:00Z",
"files": [
{
"id": "abc-123-def",
"field": "resume",
"filename": "resume.pdf",
"size": 245760,
"mime_type": "application/pdf"
}
]
}
}
Not Found
Status Code: 404 Not Found
{
"message": "Not found."
}
Export Submissions
GET /api/forms/{form_uuid}/submissions/export
Export submissions in bulk. The response format depends on the format query parameter.
Query Parameters
| Parameter | Required | Description |
|---|---|---|
format | No | csv (default) or json |
spam_status | No | Filter by spam classification: clean, spam, pending, or suspicious |
CSV Export
When format=csv, the API responds with a downloadable file.
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
-o submissions.csv \
"https://a.firaform.com/api/forms/{form_uuid}/submissions/export?format=csv"
Response Headers:
Content-Type: text/csv
Content-Disposition: attachment; filename="submissions.csv"
The CSV includes all form fields as columns plus metadata columns (IP, location, device, etc.). File contents are not embedded — use the Download File endpoint to fetch attachments individually.
JSON Export
When format=json, the API returns a JSON array of all matching submissions (not paginated).
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
"https://a.firaform.com/api/forms/{form_uuid}/submissions/export?format=json&spam_status=clean"
Status Code: 200 OK
[
{
"id": 123456,
"data": { "name": "John Doe", "email": "[email protected]" },
"spam_status": "clean",
"created_at": "2026-01-21T14:30:00Z"
},
{
"id": 123457,
"data": { "name": "Jane Smith", "email": "[email protected]" },
"spam_status": "clean",
"created_at": "2026-01-22T09:15:00Z"
}
]
Delete Submission
DELETE /api/forms/{form_uuid}/submissions/{id}
Permanently deletes a submission and all associated uploaded files. This action cannot be undone.
Authorization: Team owners and admins only. See Authorization.
Example Request
curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://a.firaform.com/api/forms/{form_uuid}/submissions/123456
Success Response
Status Code: 200 OK
{
"success": true,
"message": "Submission deleted."
}
Forbidden
Status Code: 403 Forbidden
{
"message": "You do not have permission to delete this submission."
}
Download File
GET /api/files/{file_id}/download
Returns a temporary signed URL for downloading an uploaded file. The URL expires after 1 hour.
Use the file_id from a submission’s files array (see Get Single Submission).
Example Request
curl -H "Authorization: Bearer YOUR_API_TOKEN" \
https://a.firaform.com/api/files/{file_id}/download
Example Response
Status Code: 200 OK
{
"url": "https://files.firaform.com/signed/abc123...&expires=1737475800",
"expires_at": "2026-01-21T15:30:00Z"
}
Fetch the file from the returned url within the hour. No authentication is required on the signed URL itself, which makes it safe to pass to a browser or downstream service for a limited time.
Example: Download the File
# 1. Get the signed URL
SIGNED_URL=$(curl -s -H "Authorization: Bearer YOUR_API_TOKEN" \
https://a.firaform.com/api/files/{file_id}/download | jq -r '.url')
# 2. Download the actual file (no auth header needed)
curl -o resume.pdf "$SIGNED_URL"
Public Form Submission (No Auth)
End-users submitting forms from your website do not need an API token. They submit directly to the public endpoint:
POST /api/f/{form_uuid}
This endpoint requires domain validation (the Referer must match your allowed domains) and CAPTCHA verification when enabled. See the API Reference for full details on HTML, JSON, and file-upload submission formats.
Authorization
Access to submissions is scoped by team membership:
| Action | Who can perform it |
|---|---|
| Viewing submissions | Any team member |
| Deleting submissions | Team owners and admins only |
| Accessing another team’s form | Blocked — returns 403 Forbidden |
Cross-Team Access
Requests for a form that does not belong to the authenticated user’s team return:
Status Code: 403 Forbidden
{
"message": "You do not have permission to access this form."
}
Rate Limiting
All API routes are throttled via the api rate limiter (configured in bootstrap/app.php). Exceeding the limit returns:
Status Code: 429 Too Many Requests
{
"message": "Too many requests. Please try again later."
}
If your integration polls frequently, consider using webhooks instead — they push data to you in real time and avoid rate-limit overhead. See Integrations → Webhooks.
Examples
JavaScript: Fetch and Paginate All Clean Submissions
const token = process.env.FIRAFORM_TOKEN;
const formUuid = 'YOUR-FORM-UUID';
let page = 1;
let allSubmissions = [];
while (true) {
const res = await fetch(
`https://a.firaform.com/api/forms/${formUuid}/submissions?spam_status=clean&per_page=100&page=${page}`,
{ headers: { Authorization: `Bearer ${token}` } }
);
if (!res.ok) {
throw new Error(`Request failed: ${res.status} ${res.statusText}`);
}
const { data, meta } = await res.json();
allSubmissions.push(...data);
if (page >= meta.last_page) break;
page++;
}
console.log(`Fetched ${allSubmissions.length} clean submissions`);
JavaScript: Export to JSON
const res = await fetch(
'https://a.firaform.com/api/forms/YOUR-FORM-UUID/submissions/export?format=json',
{ headers: { Authorization: `Bearer ${process.env.FIRAFORM_TOKEN}` } }
);
const submissions = await res.json();
console.log(submissions);
curl: Delete a Submission
curl -X DELETE \
-H "Authorization: Bearer YOUR_API_TOKEN" \
https://a.firaform.com/api/forms/{form_uuid}/submissions/123456
curl: Download an Uploaded File
SIGNED_URL=$(curl -s -H "Authorization: Bearer YOUR_API_TOKEN" \
https://a.firaform.com/api/files/{file_id}/download | jq -r '.url')
curl -o file.bin "$SIGNED_URL"
Best Practices
- Store tokens in environment variables — never hardcode them in source files.
- Use the least-privileged token — create separate tokens per integration and revoke unused ones from
/profile/tokens. - Page through results — always check
meta.last_pageinstead of assuming a single page. - Prefer webhooks for real-time sync — polling the list endpoint burns rate-limit quota.
- Cache signed download URLs briefly — they live for 1 hour; don’t request a new one on every click.
- Filter with
spam_status— pull onlycleansubmissions into downstream systems to keep spam out of your CRM. - Handle 429 gracefully — implement exponential backoff when you hit rate limits.
- Delete with care —
DELETEremoves the submission and its files permanently.
Related Documentation
- API Reference — Public form submission endpoint, CAPTCHA, webhooks, and CORS
- Form Submissions — Managing submissions from the web dashboard
- Integrations — Webhooks and third-party integrations
- Teams — Roles, permissions, and team membership