Docs

Comprehensive guides and references for FiraForm.

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:

  1. From the web dashboard — Go to Profile → API Tokens at /profile/tokens and create a new token. This is the recommended way for most users.
  2. Via the API — Send a POST /api/login request 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"
}
FieldRequiredDescription
emailYesThe email address of your FiraForm account
passwordYesYour 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

ParameterRequiredDescription
spam_statusNoFilter by spam classification: clean, spam, pending, or suspicious
per_pageNoItems per page (1–100). Default is 15
pageNoPage 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

ParameterRequiredDescription
formatNocsv (default) or json
spam_statusNoFilter 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:

ActionWho can perform it
Viewing submissionsAny team member
Deleting submissionsTeam owners and admins only
Accessing another team’s formBlocked — 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

  1. Store tokens in environment variables — never hardcode them in source files.
  2. Use the least-privileged token — create separate tokens per integration and revoke unused ones from /profile/tokens.
  3. Page through results — always check meta.last_page instead of assuming a single page.
  4. Prefer webhooks for real-time sync — polling the list endpoint burns rate-limit quota.
  5. Cache signed download URLs briefly — they live for 1 hour; don’t request a new one on every click.
  6. Filter with spam_status — pull only clean submissions into downstream systems to keep spam out of your CRM.
  7. Handle 429 gracefully — implement exponential backoff when you hit rate limits.
  8. Delete with careDELETE removes the submission and its files permanently.
  • 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