Formester API v2 Documentation

Introduction

Formester API v2 is a powerful REST API that provides access to your forms and submissions. V2 introduces organization-level access and improved response formats.

What's New in V2

FeatureV1V2
Token scopeForm-levelOrganization-level
PaginationFixed 20/pageFixed 20/page
Response formatresults arrayNamed arrays + meta

Base URL

All API requests should be made to:

https://app.formester.com/api/v2

Quick Reference

MethodEndpointScope RequiredDescription
GET/formsform.viewList all forms
GET/forms/:idform.viewGet a specific form, including its element IDs
GET/submissionssubmission.viewList all submissions
GET/submissions/:idsubmission.viewGet a specific submission
DELETE/submissions/:idsubmission.deleteDelete a submission
GET/forms/:form_uuid/prefillsprefill.readList prefills for a form
GET/forms/:form_uuid/prefills/:idprefill.readGet a specific prefill
POST/forms/:form_uuid/prefillsprefill.writeBulk create prefills
DELETE/forms/:form_uuid/prefillsprefill.writeBulk delete prefills
GET/forms/:form_uuid/unique_linksunique_link.readList unique links for a form
GET/forms/:form_uuid/unique_links/:idunique_link.readGet a specific unique link
PATCH/forms/:form_uuid/unique_links/:idunique_link.writeUpdate a unique link
POST/forms/:form_uuid/unique_linksunique_link.writeBulk create unique links
DELETE/forms/:form_uuid/unique_linksunique_link.writeBulk delete unique links

Authentication

All API requests require authentication using the X-FORMESTER-TOKEN header.

Request Header

X-FORMESTER-TOKEN: your-access-token

Obtaining a Token

To obtain an API v2 access token, visit app.formester.com/apiopen in new window in your Formester dashboard.

Token Characteristics

  • Organization-level access: V2 tokens provide access to all forms within your organization, or can be restricted to specific forms.
  • Scoped permissions: Each token has specific scopes that determine what operations it can perform.
  • Usage tracking: Token usage is tracked to help you monitor API consumption.
  • Revocable: Tokens can be revoked at any time for security purposes.

Scopes

V2 tokens use scopes to control access to API operations.

ScopeDescriptionEndpoints
form.viewRead access to formsGET /forms, GET /forms/:id
submission.viewRead access to submissionsGET /submissions, GET /submissions/:id
submission.deleteDelete submissionsDELETE /submissions/:id
prefill.readRead access to prefillsGET /forms/:form_uuid/prefills, GET /forms/:form_uuid/prefills/:id
prefill.writeCreate and delete prefillsPOST /forms/:form_uuid/prefills, DELETE /forms/:form_uuid/prefills
unique_link.readRead access to unique linksGET /forms/:form_uuid/unique_links, GET /forms/:form_uuid/unique_links/:id
unique_link.writeCreate, update and delete unique linksPOST /forms/:form_uuid/unique_links, PATCH /forms/:form_uuid/unique_links/:id, DELETE /forms/:form_uuid/unique_links

Scope Error Response

If your token lacks the required scope for an operation:

HTTP/1.1 403 Forbidden

{
  "message": "You do not have permission to perform this action. Required scope: submission.delete"
}

Rate Limiting

To ensure fair usage and platform stability, the API enforces rate limits:

LimitValue
Maximum requests10 per 60 seconds
PerToken

Rate Limit Response

When you exceed the rate limit:

HTTP/1.1 429 Too Many Requests

{
  "message": "You have exceeded api rate limit"
}

Endpoints

Forms

List Forms

Retrieve a list of all forms accessible with your token.

Endpoint

GET /api/v2/forms

Required Scope: form.view

Query Parameters

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number

cURL Example

curl -X GET "https://app.formester.com/api/v2/forms" \
  -H "X-FORMESTER-TOKEN: your-access-token"

# With pagination
curl -X GET "https://app.formester.com/api/v2/forms?page=2" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "forms": [
    {
      "id": 123,
      "uuid": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Contact Form",
      "createdAt": "2024-01-15T10:30:00.000Z",
      "updatedAt": "2024-01-20T14:45:00.000Z",
      "submissionsCount": 42
    },
    {
      "id": 456,
      "uuid": "660e8400-e29b-41d4-a716-446655440001",
      "name": "Feedback Survey",
      "createdAt": "2024-02-01T09:00:00.000Z",
      "updatedAt": "2024-02-05T11:30:00.000Z",
      "submissionsCount": 128
    }
  ],
  "meta": {
    "totalCount": 5,
    "page": 1,
    "perPage": 20
  }
}

Response Fields

FieldTypeDescription
formsarrayArray of form objects
forms[].idintegerNumeric form identifier
forms[].uuidstringUnique form identifier (UUID)
forms[].namestringForm name
forms[].createdAtstringISO 8601 creation timestamp
forms[].updatedAtstringISO 8601 last update timestamp
forms[].submissionsCountintegerTotal number of submissions
meta.totalCountintegerTotal number of forms
meta.pageintegerCurrent page number
meta.perPageintegerItems per page

Get Form

Retrieve a single form's metadata along with its element tree. This is the primary way to discover a form's element IDs, which are required when building prefill_data for Prefills and Unique Links (each prefill_data entry maps an element id to a value: {"id": "el_email_1", "value": "..."})

Endpoint

GET /api/v2/forms/:id

Required Scope: form.view

Path Parameters

ParameterTypeRequiredDescription
idstringYesForm UUID (numeric form ID also accepted)

cURL Example

curl -X GET "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "id": 123,
  "name": "Contact Form",
  "createdAt": "2024-01-15T10:30:00.000Z",
  "updatedAt": "2024-01-20T14:45:00.000Z",
  "submissionsCount": 42,
  "elements": [
    {"id": "el_name_1", "label": "Full Name", "type": "short-text"},
    {"id": "el_email_1", "label": "Email", "type": "email"},
    {
      "id": "el_choice_1",
      "label": "Favourite Colour",
      "type": "dropdown",
      "options": [
        {"id": "opt-uuid-abc123", "label": "Red", "value": "red"},
        {"id": "opt-uuid-def456", "label": "Blue", "value": "blue"}
      ]
    }
  ]
}

Response Fields

FieldTypeDescription
idintegerNumeric form identifier
namestringForm name
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last update timestamp
submissionsCountintegerTotal number of submissions
elementsarrayForm's element tree (flattened to the fields below)
elements[].idstringElement ID — use this as prefill_data[].id when prefilling this field
elements[].labelstringElement label
elements[].typestringElement type (e.g. short-text, email, dropdown, matrix, repeat-field, name, address, phone)
elements[].optionsarray{id, label, value} choices, present for choice-based types (radio, multiple-checkbox, dropdown, picture-checkbox, ranking) — use id when prefilling these fields
elements[].rows / elements[].columnsarrayRow/column definitions, present for matrix elements
elements[].componentsarrayNested element list, present for repeat-field elements
elements[].childrenarrayNested {fixedname, label, required} sub-fields, present for name/address elements

If the form cannot be found:

HTTP/1.1 404 Not Found

{
  "message": "Form not found or not authorized"
}

Submissions

List Submissions

Retrieve a list of all submissions with optional filtering and sorting.

Endpoint

GET /api/v2/submissions

Required Scope: submission.view

Query Parameters

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number
form_idintegerYes*-Form numeric ID
form_uuidstringYes*-Form UUID
sortstringNo-Field name to sort by
orderstringNoascSort order: asc or desc
{field}stringNo-Filter by exact match
{field}__gtestringNo-Filter: greater than or equal
{field}__gtstringNo-Filter: greater than
{field}__ltestringNo-Filter: less than or equal
{field}__ltstringNo-Filter: less than

*Either form_id or form_uuid is required. Use form_id for numeric ID or form_uuid for UUID.

cURL Examples

# Using form_uuid (recommended)
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000" \
  -H "X-FORMESTER-TOKEN: your-access-token"

# Using form_id (numeric)
curl -X GET "https://app.formester.com/api/v2/submissions?form_id=123" \
  -H "X-FORMESTER-TOKEN: your-access-token"

# With pagination
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000&page=2" \
  -H "X-FORMESTER-TOKEN: your-access-token"

# With filtering
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000&Rating__gte=3" \
  -H "X-FORMESTER-TOKEN: your-access-token"

# With sorting
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000&sort=created_at&order=desc" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "submissions": [
    {
      "id": "770e8400-e29b-41d4-a716-446655440002",
      "formId": "550e8400-e29b-41d4-a716-446655440000",
      "data": {
        "email": "[email protected]",
        "name": "John Doe",
        "message": "Hello, I have a question."
      },
      "createdAt": "2024-01-20T10:00:00.000Z",
      "updatedAt": "2024-01-20T10:00:00.000Z"
    },
    {
      "id": "880e8400-e29b-41d4-a716-446655440003",
      "formId": "550e8400-e29b-41d4-a716-446655440000",
      "data": {
        "email": "[email protected]",
        "name": "Jane Smith",
        "message": "Great service!"
      },
      "createdAt": "2024-01-19T15:30:00.000Z",
      "updatedAt": "2024-01-19T15:30:00.000Z"
    }
  ],
  "meta": {
    "formId": 123,
    "formUuid": "550e8400-e29b-41d4-a716-446655440000",
    "totalCount": 150,
    "page": 1,
    "perPage": 20
  }
}

Response Fields

FieldTypeDescription
submissionsarrayArray of submission objects
submissions[].idstringUnique submission identifier (UUID)
submissions[].formIdstringUUID of the form this submission belongs to
submissions[].dataobjectSubmitted form data
submissions[].createdAtstringISO 8601 creation timestamp
submissions[].updatedAtstringISO 8601 last update timestamp
meta.formIdintegerNumeric ID of the form
meta.formUuidstringUUID of the form
meta.totalCountintegerTotal number of submissions
meta.pageintegerCurrent page number
meta.perPageintegerItems per page

Get Submission

Retrieve a specific submission by its UUID.

Endpoint

GET /api/v2/submissions/:id

Required Scope: submission.view

Path Parameters

ParameterTypeRequiredDescription
idstringYesSubmission UUID

cURL Example

curl -X GET "https://app.formester.com/api/v2/submissions/770e8400-e29b-41d4-a716-446655440002" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "submission": {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "formId": "550e8400-e29b-41d4-a716-446655440000",
    "data": {
      "email": "[email protected]",
      "name": "John Doe",
      "message": "Hello, I have a question."
    },
    "createdAt": "2024-01-20T10:00:00.000Z",
    "updatedAt": "2024-01-20T10:00:00.000Z"
  }
}

Delete Submission

Delete a specific submission.

Endpoint

DELETE /api/v2/submissions/:id

Required Scope: submission.delete

Path Parameters

ParameterTypeRequiredDescription
idstringYesSubmission UUID

cURL Example

curl -X DELETE "https://app.formester.com/api/v2/submissions/770e8400-e29b-41d4-a716-446655440002" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "message": "Submission deleted successfully"
}

Prefills

Prefills let you pre-populate a form's fields for a recipient by passing a _prefill UUID in the form's survey URL. They are scoped to a specific form, addressed via :form_uuid in the path.

Each prefill's data is an array of {id, value} pairs, where id is a form element's ID. Use Get Form (GET /api/v2/forms/:id) to look up a form's elements[].id values before constructing data.

List Prefills

Retrieve a paginated list of prefills for a form.

Endpoint

GET /api/v2/forms/:form_uuid/prefills

Required Scope: prefill.read

Path Parameters

ParameterTypeRequiredDescription
form_uuidstringYesForm UUID (numeric form ID also accepted)

Query Parameters

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number
namestringNo-Filter by prefill name (partial match)
include_unique_link_prefillsbooleanNofalseInclude prefills generated for unique links

cURL Example

curl -X GET "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000/prefills" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "prefills": [
    {
      "id": "990e8400-e29b-41d4-a716-446655440004",
      "name": "John Doe",
      "url": "https://app.formester.com/f/550e8400-e29b-41d4-a716-446655440000?_prefill=990e8400-e29b-41d4-a716-446655440004",
      "createdAt": "2024-01-20T10:00:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "perPage": 20,
    "total": 1
  }
}

Response Fields

FieldTypeDescription
prefillsarrayArray of prefill objects
prefills[].idstringUnique prefill identifier (UUID)
prefills[].namestringPrefill name
prefills[].urlstringSurvey URL with the _prefill query parameter applied
prefills[].createdAtstringISO 8601 creation timestamp
meta.pageintegerCurrent page number
meta.perPageintegerItems per page
meta.totalintegerTotal number of prefills

Get Prefill

Retrieve a specific prefill by its UUID, including its prefill data.

Endpoint

GET /api/v2/forms/:form_uuid/prefills/:id

Required Scope: prefill.read

Path Parameters

ParameterTypeRequiredDescription
form_uuidstringYesForm UUID (numeric form ID also accepted)
idstringYesPrefill UUID

cURL Example

curl -X GET "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000/prefills/990e8400-e29b-41d4-a716-446655440004" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "id": "990e8400-e29b-41d4-a716-446655440004",
  "name": "John Doe",
  "url": "https://app.formester.com/f/550e8400-e29b-41d4-a716-446655440000?_prefill=990e8400-e29b-41d4-a716-446655440004",
  "createdAt": "2024-01-20T10:00:00.000Z",
  "data": [
    {"id": "el_name_1", "value": "John Doe"},
    {"id": "el_email_1", "value": "[email protected]"}
  ]
}

Response Fields

FieldTypeDescription
idstringUnique prefill identifier (UUID)
namestringPrefill name
urlstringSurvey URL with the _prefill query parameter applied
createdAtstringISO 8601 creation timestamp
dataarrayArray of {id, value} pairs mapping form element IDs to prefill values

If the prefill cannot be found:

HTTP/1.1 404 Not Found

{
  "message": "Prefill not found"
}

Bulk Create Prefills

Create one or more prefills for a form in a single request.

Endpoint

POST /api/v2/forms/:form_uuid/prefills

Required Scope: prefill.write

Path Parameters

ParameterTypeRequiredDescription
form_uuidstringYesForm UUID (numeric form ID also accepted)

Body Parameters

ParameterTypeRequiredDescription
prefillsarrayYesArray of prefill objects to create
prefills[].namestringYesPrefill name
prefills[].prefill_dataarrayYesArray of {id, value} pairs mapping form element IDs to prefill values

cURL Example

curl -X POST "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000/prefills" \
  -H "X-FORMESTER-TOKEN: your-access-token" \
  -H "Content-Type: application/json" \
  -d '{
    "prefills": [
      {
        "name": "John Doe",
        "prefill_data": [
          {"id": "el_name_1", "value": "John Doe"},
          {"id": "el_email_1", "value": "[email protected]"}
        ]
      }
    ]
  }'

Response

HTTP/1.1 201 Created
Content-Type: application/json
{
  "prefills": [
    {
      "prefillId": "990e8400-e29b-41d4-a716-446655440004",
      "url": "https://app.formester.com/f/550e8400-e29b-41d4-a716-446655440000?_prefill=990e8400-e29b-41d4-a716-446655440004",
      "name": "John Doe"
    }
  ]
}

Response Fields

FieldTypeDescription
prefillsarrayArray of created prefill objects
prefills[].prefillIdstringUnique prefill identifier (UUID)
prefills[].urlstringSurvey URL with the _prefill query parameter applied
prefills[].namestringPrefill name

Validation Errors

StatusError messageNotes
400prefills is required and must be an arrayBody missing or not an array
400too many prefills (max 100)Batch exceeds limit
400prefills[0].name is requiredname is mandatory for every item
400prefills[0].prefill_data is required and must be an arrayprefill_data is mandatory and must be an array

For prefill_data structure errors (invalid element IDs, wrong value types) see Prefill Data Errors.


Bulk Delete Prefills

Delete one or more prefills by UUID.

Endpoint

DELETE /api/v2/forms/:form_uuid/prefills

Required Scope: prefill.write

Path Parameters

ParameterTypeRequiredDescription
form_uuidstringYesForm UUID (numeric form ID also accepted)

Body Parameters

ParameterTypeRequiredDescription
idsarrayYesArray of prefill UUIDs to delete (max 100)

cURL Example

curl -X DELETE "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000/prefills" \
  -H "X-FORMESTER-TOKEN: your-access-token" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["990e8400-e29b-41d4-a716-446655440004", "aa0e8400-e29b-41d4-a716-446655440005"]}'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "deleted": 2
}

Validation Errors

StatusError messageNotes
400ids is requiredBody missing ids key
400ids must be an arrayids is not an array
400too many ids (max 100)Batch exceeds limit
422{ "error": "Prefill IDs not found", "notFoundIds": [...] }One or more UUIDs not found

Unique links are per-recipient survey links that can carry their own prefill data, expiry, and submission status. They are scoped to a specific form, addressed via :form_uuid in the path.

When supplying prefill_data on create/update, each entry is {id, value} where id is a form element's ID. Use Get Form (GET /api/v2/forms/:id) to look up a form's elements[].id values beforehand.

Retrieve a paginated list of unique links for a form.

Endpoint

GET /api/v2/forms/:form_uuid/unique_links

Required Scope: unique_link.read

Path Parameters

ParameterTypeRequiredDescription
form_uuidstringYesForm UUID (numeric form ID also accepted)

Query Parameters

ParameterTypeRequiredDefaultDescription
pageintegerNo1Page number
entry_namestringNo-Filter by entry name (partial match)
include_prefill_databooleanNofalseInclude the linked prefill's prefill_data in the response

cURL Example

curl -X GET "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000/unique_links?include_prefill_data=true" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "uniqueLinks": [
    {
      "id": "bb0e8400-e29b-41d4-a716-446655440006",
      "entryName": "Onboarding Link",
      "status": "pending",
      "active": true,
      "expiresAt": "2024-03-01T00:00:00.000Z",
      "url": "https://app.formester.com/u/bb0e8400-e29b-41d4-a716-446655440006",
      "prefillId": "990e8400-e29b-41d4-a716-446655440004",
      "createdAt": "2024-01-20T10:00:00.000Z",
      "prefillData": [
        {"id": "el_email_1", "value": "[email protected]"}
      ]
    }
  ],
  "meta": {
    "page": 1,
    "perPage": 20,
    "total": 1
  }
}

Response Fields

FieldTypeDescription
uniqueLinksarrayArray of unique link objects
uniqueLinks[].idstringUnique link identifier (UUID)
uniqueLinks[].entryNamestringRecipient/entry name
uniqueLinks[].statusstringSubmission status: pending, in_progress, or completed
uniqueLinks[].activebooleanWhether the link is active
uniqueLinks[].expiresAtstringISO 8601 expiration timestamp, or null
uniqueLinks[].urlstringSurvey URL for this unique link
uniqueLinks[].prefillIdstringUUID of the linked prefill, or null
uniqueLinks[].createdAtstringISO 8601 creation timestamp
uniqueLinks[].prefillDataarrayLinked prefill's {id, value} data (only when include_prefill_data=true)
meta.pageintegerCurrent page number
meta.perPageintegerItems per page
meta.totalintegerTotal number of unique links

Retrieve a specific unique link by its UUID.

Endpoint

GET /api/v2/forms/:form_uuid/unique_links/:id

Required Scope: unique_link.read

Path Parameters

ParameterTypeRequiredDescription
form_uuidstringYesForm UUID (numeric form ID also accepted)
idstringYesUnique link UUID

Query Parameters

ParameterTypeRequiredDefaultDescription
include_prefill_databooleanNofalseInclude the linked prefill's prefill_data in the response

cURL Example

curl -X GET "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000/unique_links/bb0e8400-e29b-41d4-a716-446655440006?include_prefill_data=true" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "id": "bb0e8400-e29b-41d4-a716-446655440006",
  "entryName": "Onboarding Link",
  "status": "pending",
  "active": true,
  "expiresAt": "2024-03-01T00:00:00.000Z",
  "url": "https://app.formester.com/u/bb0e8400-e29b-41d4-a716-446655440006",
  "prefillId": "990e8400-e29b-41d4-a716-446655440004",
  "createdAt": "2024-01-20T10:00:00.000Z",
  "prefillData": [
    {"id": "el_email_1", "value": "[email protected]"}
  ]
}

Response Fields

FieldTypeDescription
idstringUnique link identifier (UUID)
entryNamestringRecipient/entry name
statusstringSubmission status: pending, in_progress, or completed
activebooleanWhether the link is active
expiresAtstringISO 8601 expiration timestamp, or null
urlstringSurvey URL for this unique link
prefillIdstringUUID of the linked prefill, or null
createdAtstringISO 8601 creation timestamp
prefillDataarrayLinked prefill's {id, value} data (only when include_prefill_data=true)

If the unique link cannot be found:

HTTP/1.1 404 Not Found

{
  "message": "Unique link not found"
}

Create one or more unique links for a form in a single request, optionally attaching prefill data to each.

Endpoint

POST /api/v2/forms/:form_uuid/unique_links

Required Scope: unique_link.write

Path Parameters

ParameterTypeRequiredDescription
form_uuidstringYesForm UUID (numeric form ID also accepted)

Body Parameters

ParameterTypeRequiredDescription
unique_linksarrayYesArray of unique link objects to create (max 100)
unique_links[].entry_namestringNoRecipient/entry name (must be unique per form; defaults to a generated ID)
unique_links[].expires_atstringNoISO 8601 expiration timestamp
unique_links[].prefill_dataarrayNoArray of {id, value} pairs; when present, a prefill is created and attached to the link

cURL Example

curl -X POST "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000/unique_links" \
  -H "X-FORMESTER-TOKEN: your-access-token" \
  -H "Content-Type: application/json" \
  -d '{
    "unique_links": [
      {
        "entry_name": "Jane Smith",
        "expires_at": "2024-03-01T00:00:00.000Z",
        "prefill_data": [
          {"id": "el_email_1", "value": "[email protected]"}
        ]
      }
    ]
  }'

Response

HTTP/1.1 201 Created
Content-Type: application/json
{
  "uniqueLinks": [
    {
      "id": "bb0e8400-e29b-41d4-a716-446655440006",
      "entryName": "Jane Smith",
      "url": "https://app.formester.com/u/bb0e8400-e29b-41d4-a716-446655440006",
      "expiresAt": "2024-03-01T00:00:00.000Z",
      "prefillId": "990e8400-e29b-41d4-a716-446655440004"
    }
  ]
}

Response Fields

FieldTypeDescription
uniqueLinksarrayArray of created unique link objects
uniqueLinks[].idstringUnique link identifier (UUID)
uniqueLinks[].entryNamestringRecipient/entry name
uniqueLinks[].urlstringSurvey URL for this unique link
uniqueLinks[].expiresAtstringISO 8601 expiration timestamp, or null
uniqueLinks[].prefillIdstringUUID of the created prefill, or null if no prefill_data was supplied

Field Value Formats

The format of each prefill_data[].value depends on the element type. Use Get Form (GET /api/v2/forms/:id) to discover element types along with their option, row, and column IDs before constructing prefill_data.

Field typeValue formatExample
short-text, long-text, email, number, date, hiddenPlain string or number"Jane Smith"
phoneString — see Phone field values for accepted formats"+1-4155550123"
radio, dropdown, picture-checkboxOption ID string (from elements[].options[].id)"opt-uuid-abc123"
multiple-checkbox, rankingArray of option ID strings["opt-uuid-abc123", "opt-uuid-def456"]
matrixObject keyed by row ID → object keyed by column ID → cell value{"row-uuid-1": {"col-uuid-a": "Yes", "col-uuid-b": "No"}}
repeat-fieldArray of objects; each object maps component element IDs to their values (one object per repeated row)[{"comp-uuid-1": "Jane", "comp-uuid-2": "Doe"}, {"comp-uuid-1": "John", "comp-uuid-2": "Smith"}]

Choices fields (radio, dropdown, multiple-checkbox, picture-checkbox, ranking): pass the option id returned by Get Form in elements[].options[].id — not the human-readable label or value.

Matrix: outer keys are row id values from elements[].rows; inner keys are column id values from elements[].columns.

Repeat field: each array entry represents one repeated row. Keys are the component element id values from elements[].components.

Validation Errors

StatusError messageNotes
400unique_links is required and must be an arrayBody missing or not an array
400too many unique_links (max 100)Batch exceeds limit
400unique_links[0].prefill_data must be an arraySee Prefill Data Errors for structure errors
400unique_links[0].expires_at is not a valid dateSee expires_at Errors
400unique_links[0].expires_at must be in the futureSee expires_at Errors
422Duplicate entry_name for this formentry_name must be unique per form

Update a unique link's entry name, expiry, active state, and/or attached prefill data.

Endpoint

PATCH /api/v2/forms/:form_uuid/unique_links/:id

Required Scope: unique_link.write

Path Parameters

ParameterTypeRequiredDescription
form_uuidstringYesForm UUID (numeric form ID also accepted)
idstringYesUnique link UUID

Body Parameters

ParameterTypeRequiredDescription
entry_namestringNoNew recipient/entry name (must be unique per form; cannot be blank)
expires_atstring|nullNoNew ISO 8601 expiration timestamp; pass null or empty string to remove expiry
activebooleanNoWhether the link is active
prefill_dataarrayNoArray of {id, value} pairs; replaces (or creates) the linked prefill's data

cURL Example

curl -X PATCH "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000/unique_links/bb0e8400-e29b-41d4-a716-446655440006" \
  -H "X-FORMESTER-TOKEN: your-access-token" \
  -H "Content-Type: application/json" \
  -d '{
    "entry_name": "Jane S.",
    "active": false,
    "prefill_data": [{"id": "el_email_1", "value": "[email protected]"}]
  }'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "id": "bb0e8400-e29b-41d4-a716-446655440006",
  "entryName": "Jane S.",
  "status": "pending",
  "active": false,
  "expiresAt": "2024-03-01T00:00:00.000Z",
  "url": "https://app.formester.com/u/bb0e8400-e29b-41d4-a716-446655440006",
  "prefillId": "990e8400-e29b-41d4-a716-446655440004",
  "createdAt": "2024-01-20T10:00:00.000Z"
}

Response Fields

Same shape as a list response item (without prefill_data, unless requested separately via the list endpoint).

Validation Errors

StatusError messageNotes
400entry_name cannot be blankentry_name key present but empty
400prefill_data must be an arraySee Prefill Data Errors for structure errors
400expires_at is not a valid dateSee expires_at Errors
400expires_at must be in the futureSee expires_at Errors
422Duplicate entry_name for this formentry_name must be unique per form
404Unique link not foundUUID not found or not accessible

Delete one or more unique links by UUID. Linked prefills are destroyed along with their unique link.

Endpoint

DELETE /api/v2/forms/:form_uuid/unique_links

Required Scope: unique_link.write

Path Parameters

ParameterTypeRequiredDescription
form_uuidstringYesForm UUID (numeric form ID also accepted)

Body Parameters

ParameterTypeRequiredDescription
idsarrayYesArray of unique link UUIDs to delete (max 100)

cURL Example

curl -X DELETE "https://app.formester.com/api/v2/forms/550e8400-e29b-41d4-a716-446655440000/unique_links" \
  -H "X-FORMESTER-TOKEN: your-access-token" \
  -H "Content-Type: application/json" \
  -d '{"ids": ["bb0e8400-e29b-41d4-a716-446655440006"]}'

Response

HTTP/1.1 200 OK
Content-Type: application/json
{
  "deleted": 1
}

Validation Errors

StatusError messageNotes
400ids is requiredBody missing ids key
400ids must be an arrayids is not an array
400too many ids (max 100)Batch exceeds limit
422{ "error": "Unique link IDs not found", "notFoundIds": [...] }One or more UUIDs not found

Filtering & Sorting

Filtering Submissions

The API supports powerful filtering capabilities using field-based operators.

Note: Field-based filtering (using operators like __gte, __lt, etc.) requires form_id or form_uuid to be specified.

Filter Operators

OperatorSyntaxDescriptionExample
Equals/Like{field}=valueExact match or substring[email protected]
Greater than or equal{field}__gte=value>= comparisonRating__gte=3
Greater than{field}__gt=value> comparisonRating__gt=3
Less than or equal{field}__lte=value<= comparisonRating__lte=5
Less than{field}__lt=value< comparisonRating__lt=5

Filter Examples

# Filter by form using UUID
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000" \
  -H "X-FORMESTER-TOKEN: your-access-token"

# Filter by rating range
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000&Rating__gte=3&Rating__lte=5" \
  -H "X-FORMESTER-TOKEN: your-access-token"

# Combine with sorting
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000&Rating__gte=4&sort=created_at&order=desc" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Sorting

Use the sort and order parameters to control result ordering.

ParameterValuesDescription
sortAny field nameField to sort by
orderasc, descSort direction (default: asc)
# Sort by creation date, newest first
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000&sort=created_at&order=desc" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Pagination

All list endpoints return paginated results with 20 items per page.

Pagination Parameters

ParameterDefaultDescription
page1Page number (1-indexed)

Response Meta Object

Every paginated response includes a meta object:

{
  "meta": {
    "totalCount": 150,
    "page": 1,
    "perPage": 20
  }
}
FieldDescription
totalCountTotal number of items
pageCurrent page number
perPageItems per page

Calculating Total Pages

total_pages = ceil(total_count / per_page)

Pagination Examples

# First page
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000&page=1" \
  -H "X-FORMESTER-TOKEN: your-access-token"

# Second page
curl -X GET "https://app.formester.com/api/v2/submissions?form_uuid=550e8400-e29b-41d4-a716-446655440000&page=2" \
  -H "X-FORMESTER-TOKEN: your-access-token"

Error Codes

Prefill Data Errors

These errors can occur on any endpoint that accepts a prefill_data array (Bulk Create Prefills, Bulk Create Unique Links, Update Unique Link).

StatusError messageCause
400prefill_data[0].id is requiredAn entry in prefill_data is missing the id field
400prefill_data[0].id 'el_unknown' does not exist in this formThe element ID does not exist in the form
400prefill_data[0].value must be a scalar for 'short-text' fieldValue type does not match the field type
400prefill_data[0].value must be an array for 'multiple-checkbox' fieldMulti-select fields require an array value
400prefill_data[0].value must be a hash for 'matrix' fieldMatrix fields require an object value
400prefill_data[0].value must be an array for 'repeat-field'Repeat fields require an array value

Phone field values

For phone elements, pass the value as a string. The accepted formats are:

FormatExampleWhen to use
{dialCode}-{localNumber}"+91-9876543210"Field has country selector enabled — dial code prefix is stripped and the country is resolved automatically
{dialCode}{localNumber}"+919876543210"Same as above; the hyphen separator is optional
Local digits only"9876543210"Field has country selector disabled — value is stored as-is

When the country selector is enabled, the dial code is matched longest-prefix-first against the E.164 dial code list. +1 always resolves to the United States. Whitespace is stripped before matching; non-digit characters other than a leading + are removed from the local number.

Use Get Form (GET /api/v2/forms/:id) to look up valid element IDs and their types before constructing prefill_data.


expires_at Errors

These errors can occur on any endpoint that accepts an expires_at value (Bulk Create Unique Links, Update Unique Link).

StatusError messageCause
400expires_at is not a valid date (or unique_links[0].expires_at is not a valid date)Value cannot be parsed as an ISO 8601 timestamp
400expires_at must be in the future (or unique_links[0].expires_at must be in the future)Parsed date is in the past

To remove an existing expiry on a unique link, pass "expires_at": null (or an empty string) in the Update request.


HTTP Status Codes

Status CodeDescription
200Success
400Bad Request - Invalid token format or missing header
401Unauthorized - Invalid or inactive token
403Forbidden - Token lacks required scope
404Not Found - Resource not found or not authorized
429Too Many Requests - Rate limit exceeded
500Internal Server Error

Error Response Format

{
  "message": "Error description"
}

Common Error Responses

Missing Token:

HTTP/1.1 400 Bad Request

{
  "message": "Access Token not found"
}

Invalid Token:

HTTP/1.1 400 Bad Request

{
  "message": "Invalid token provided"
}

Inactive Token:

HTTP/1.1 401 Unauthorized

{
  "message": "Invalid access token"
}

Missing Scope:

HTTP/1.1 403 Forbidden

{
  "message": "You do not have permission to perform this action. Required scope: submission.delete"
}

Resource Not Found:

HTTP/1.1 404 Not Found

{
  "message": "Submission not found"
}

Form Not Authorized:

HTTP/1.1 404 Not Found

{
  "message": "Form not found or not authorized"
}

Rate Limit Exceeded:

HTTP/1.1 429 Too Many Requests

{
  "message": "You have exceeded api rate limit"
}

Migration Guide from V1

Key Changes

  1. Token Type: V2 tokens are organization-scoped, not form-scoped.
  2. Response Format: V2 uses named arrays (forms, submissions) with a meta object.
  3. Pagination: Both V1 and V2 use fixed 20 items per page.

Response Format Comparison

V1 Response:

{
  "count": 2,
  "total_count": 100,
  "per_page": 20,
  "page": 1,
  "results": [...]
}

V2 Response:

{
  "submissions": [...],
  "meta": {
    "totalCount": 100,
    "page": 1,
    "perPage": 20
  }
}

Migration Steps

  1. Obtain a V2 token - Contact support to get an organization-level V2 token.
  2. Update endpoints - Change /api/v1/ to /api/v2/ in your API calls.
  3. Update response parsing - Access data via named arrays (forms, submissions) instead of results.
  4. Update pagination - Access pagination info from the meta object.

Best Practices

  1. Store tokens securely - Never expose your API token in client-side code.

  2. Use appropriate scopes - Request only the scopes you need.

  3. Handle rate limits - Implement exponential backoff for 429 responses.

  4. Use pagination - For large datasets, iterate through pages using the page parameter.

  5. Filter server-side - Use query parameters to filter data on the server.

  6. Cache responses - Cache API responses where appropriate.

  7. Handle errors gracefully - Check for error responses and handle them appropriately.


Support

If you encounter any issues or have questions:

  • Email: [email protected]
  • For rate limit increases or custom requirements, contact our support team.
Last Updated:
Contributors: abhay2133