Submissions API
A submission is a single response to one of your Droplet forms, carried through its workflow from first save to final completion. The Submissions API lets you create submissions (one at a time or in bulk), look them up and filter them, move them through their steps, manage assignees and reminders, archive and restore them, and pull the data back out as PDFs or spreadsheets. Reach for it whenever you need to read, drive, or export form responses programmatically.

All requests go to the base URL https://api.droplet.io, and every endpoint requires a bearer token: send Authorization: Bearer <token> on each call. See the Overview article for details on obtaining and refreshing tokens.
Successful responses share a common envelope: { "requestId": "...", "success": true, "data": { ... } }. When something goes wrong, success is false and an error object with code and message takes the place of data. Path parameters are shown with a leading colon, such as :id, which you replace with the real value. Examples show the fields you will most commonly use; a submission may carry more, so ignore any you do not recognize.
A submission's status (such as in_progress, completed, draft, or done) is set by the workflow and is read-only. You move a submission forward by advancing its step (see Updating submissions), not by setting status directly.
Listing and lookup
List submission IDs
GET /v1/submissions/ids
Returns the IDs of submissions matching your filters, along with a total count. This is the workhorse for finding submissions: filter and sort here, then hydrate the IDs you care about with the entities endpoint.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| page | query | integer | No | Zero-based page of results. |
| show | query | string | No | One of all, archived, active, or voided. |
| search | query | string | No | Free-text search across submission data. |
| formId | query | string | No | Limit to one form. |
| employeeId, employeeIds | query | string, array | No | Filter by employee. |
| version | query | string | No | Limit to one form version. |
| packetTemplateId, packetId, packetSubject | query | string | No | Filter by packet. |
| status | query | string | No | Workflow status. |
| created, modified, completed | query | string | No | Date-range filters. |
| timezone | query | string | No | Timezone applied to date filters. |
| assignedTo, assignedToEmail | query | string | No | Filter by current assignee. |
| assignedToWhen | query | string | No | One of currently, last7days, last30days, thisYear, all. |
| submittedBy, submittedByEmail | query | string | No | Filter by submitter. |
| staleTags | query | boolean | No | Include submissions with stale tags. |
| tagKey, tagValue | query | string | No | Filter by a tag key/value pair. |
| sort | query | string | No | One of id, lastCreated, lastModified, tagValue, status. Defaults to lastCreated. |
| sortOrder | query | string | No | asc or desc. |
| sortTagKey | query | string | No | Tag key to sort by when sort=tagValue. |
curl -G https://api.droplet.io/v1/submissions/ids \
-H "Authorization: Bearer <token>" \
--data-urlencode "formId=onboarding-2024" \
--data-urlencode "show=active" \
--data-urlencode "sort=lastModified"
{
"requestId": "req_8fa2",
"success": true,
"data": {
"count": 3,
"ids": [1042, 1043, 1051]
}
}
List submission tag keys
GET /v1/submissions/tags
Returns the distinct tag keys present across submissions that match your filters. Handy for building tag-based filter UIs or discovering what metadata is in play.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| show | query | string | No | One of all, archived, active, voided. |
| search, formId, version | query | string | No | Narrow the set of submissions scanned. |
| employeeId, employeeIds | query | string, array | No | Filter by employee. |
| packetTemplateId, packetId, packetSubject, status | query | string | No | Packet and status filters. |
| created, modified, completed, timezone | query | string | No | Date-range filters. |
| assignedTo, assignedToEmail, submittedBy, submittedByEmail | query | string | No | People filters. |
| tagKey, tagValue | query | string | No | Filter by an existing tag pair. |
curl -G https://api.droplet.io/v1/submissions/tags \
-H "Authorization: Bearer <token>" \
--data-urlencode "formId=onboarding-2024"
{
"requestId": "req_2c7d",
"success": true,
"data": ["department", "region", "employeeId"]
}
Retrieving submission data
Get a submission by ID
GET /v1/submissions/:id
Fetches a single submission together with the form it belongs to. The response includes the submitted data, assignee state, activity log, tags, and the form definition needed to render it.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | integer | Yes | The submission ID. |
| token | query | string | No | Access token for shared or assignee links. |
| substepId | query | string | No | Target a specific parallel substep. |
curl https://api.droplet.io/v1/submissions/1042 \
-H "Authorization: Bearer <token>"
{
"requestId": "req_a91b",
"success": true,
"data": {
"assetToken": "tok_assets_...",
"submission": {
"id": 1042,
"submittedBy": { "name": "Dana Lee", "email": "dana@acme.com" },
"created": "2026-05-01T14:22:10Z",
"modified": "2026-05-02T09:10:00Z",
"formId": "onboarding-2024",
"version": "v3",
"formName": "New Hire Onboarding",
"status": "in_progress",
"step": "manager-review",
"data": { "firstName": "Dana", "startDate": "2026-06-01" },
"tags": { "department": "Engineering" },
"progress": { "stepLabel": "Manager Review", "percent": 60 }
// ...
},
"form": {
"id": "onboarding-2024",
"name": "New Hire Onboarding",
"version": { "id": 12, "version": "v3", "locked": true }
// ...
}
}
}
Get multiple submissions
POST /v1/submissions/entities
Resolves a batch of submission IDs into full submission records in one call. Pair it with the IDs endpoint to page through results. metaOnly is required: send false for full records, or true to omit heavy field data when you only need summary info.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| includeProgress | query | string | No | Pass includeProgress=true to include per-submission progress details. |
| ids | body | array of integer | Yes | Between 1 and 50 submission IDs. |
| metaOnly | body | boolean | Yes | Return metadata only, omitting full field data. |
curl https://api.droplet.io/v1/submissions/entities \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "ids": [1042, 1043], "metaOnly": false }'
{
"requestId": "req_77ce",
"success": true,
"data": [
{
"id": 1042,
"submittedBy": { "name": "Dana Lee", "email": "dana@acme.com" },
"formId": "onboarding-2024",
"status": "in_progress",
"step": "manager-review",
"data": { "firstName": "Dana" },
"tags": { "department": "Engineering" }
// ...
}
// ...
]
}
Get a submission's activity log
GET /v1/submissions/:id/activity-log
Returns the chronological activity log for a single submission, including who acted, what step it touched, recipients, and timestamps.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | integer | Yes | The submission ID. |
curl https://api.droplet.io/v1/submissions/1042/activity-log \
-H "Authorization: Bearer <token>"
{
"requestId": "req_b034",
"success": true,
"data": {
"id": 1042,
"activityLog": [
{
"type": "submitted",
"actor": { "name": "Dana Lee", "email": "dana@acme.com" },
"step": "applicant-info",
"timestamp": "2026-05-01T14:22:10Z"
}
// ...
]
}
}
Creating submissions
Create a submission
POST /v1/submissions
Creates a single submission against a form. Use action to control intent: submit to finalize the current step, save to store progress, or packet to start a packet submission.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| formId | body | string | Yes | The form to submit against. |
| action | body | string | Yes | One of submit, save, packet. |
| data | body | object | Yes | The submission field values. |
| version | body | string | No | Specific form version. |
| packetId | body | string | No | Packet to attach the submission to. |
| submittedBy | body | object | No | Submitter name and email. |
| assignedTo | body | object | No | Initial assignee name and email. |
| savedProgress | body | object | No | Partial progress to seed the submission. |
curl https://api.droplet.io/v1/submissions \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"formId": "onboarding-2024",
"action": "submit",
"submittedBy": { "name": "Dana Lee", "email": "dana@acme.com" },
"data": { "firstName": "Dana", "startDate": "2026-06-01" }
}'
{
"requestId": "req_31ab",
"success": true,
"data": { "id": 1052 }
}
Create submissions in bulk
POST /v1/submissions/create
Creates many submissions for one form in a single request. Each entry must include submittedByName and submittedByEmail, plus any form field values as additional properties. The response reports which entries succeeded and which failed by index.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| formId | body | string | Yes | The form to submit against. |
| action | body | string | Yes | Must be submit. |
| submissions | body | array | Yes | 1 to 500 entries, each with submittedByName, submittedByEmail, and field values. |
| version | body | string | No | Specific form version. |
curl https://api.droplet.io/v1/submissions/create \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"formId": "onboarding-2024",
"action": "submit",
"submissions": [
{ "submittedByName": "Dana Lee", "submittedByEmail": "dana@acme.com", "startDate": "2026-06-01" },
{ "submittedByName": "Sam Ortiz", "submittedByEmail": "sam@acme.com", "startDate": "2026-06-08" }
]
}'
{
"requestId": "req_55de",
"success": true,
"data": {
"success": true,
"successes": [1053, 1054],
"errors": []
}
}
Duplicate a submission
POST /v1/submissions/:id/duplicate
Creates a copy of an existing submission and returns the new record along with its form. Useful for cloning a near-identical response without re-entering data.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | integer | Yes | The submission to duplicate. |
| token | query | string | No | Access token for shared links. |
curl -X POST https://api.droplet.io/v1/submissions/1042/duplicate \
-H "Authorization: Bearer <token>"
{
"requestId": "req_9a0c",
"success": true,
"data": {
"submission": {
"id": 1060,
"formId": "onboarding-2024",
"status": "draft",
"data": { "firstName": "Dana" }
// ...
},
"form": { "id": "onboarding-2024", "version": { "version": "v3" } }
// ...
}
}
Updating submissions
Update a submission
PUT /v1/submissions/:id
Saves changes to a submission's data at a given step. Use action to choose what happens: submit advances the step, save stores progress, and reject rejects the current step. The response returns the updated submission and form.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | integer | Yes | The submission ID. |
| action | body | string | Yes | One of submit, reject, save. |
| step | body | string | Yes | The step the update applies to. |
| data | body | object | Yes | The updated field values. |
| submittedBy | body | object | No | Submitter name and email. |
curl -X PUT https://api.droplet.io/v1/submissions/1042 \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"action": "submit",
"step": "manager-review",
"data": { "approved": true }
}'
{
"requestId": "req_4f12",
"success": true,
"data": {
"submission": { "id": 1042, "status": "completed", "step": "done" },
"form": { "id": "onboarding-2024", "version": { "version": "v3" } }
// ...
}
}
Assigning and reminding
Assign multiple submissions
POST /v1/submissions/assign
Assigns a set of submissions to a single person. Provide the target via assignedTo (or assignee), and optionally include a custom notification message.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| ids | body | array of integer | Yes | Submission IDs to assign. |
| assignedTo | body | object | No | Assignee name and email. |
| assignee | body | object | No | Alternate assignee field with name and email. |
| customMessage | body | object | No | Notification subject and message. |
curl https://api.droplet.io/v1/submissions/assign \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"ids": [1042, 1043],
"assignedTo": { "name": "Pat Kim", "email": "pat@acme.com" }
}'
{
"requestId": "req_60aa",
"success": true,
"data": { "success": true }
}
Reassign contributors on a submission
POST /v1/submissions/:id/assign
Assigns or reassigns one or more contributors on a single submission. Each key in reassignments maps a role or step to a new assignee.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | integer | Yes | The submission ID. |
| reassignments | body | object | Yes | Map of target keys to { name, email } assignees. |
| customMessage | body | object | No | Notification subject and message. |
curl https://api.droplet.io/v1/submissions/1042/assign \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"reassignments": {
"manager-review": { "name": "Pat Kim", "email": "pat@acme.com" }
}
}'
{
"requestId": "req_71bb",
"success": true,
"data": { "success": true }
}
Send reminders
POST /v1/submissions/remind
Sends reminder notifications to the current assignees of the listed submissions. Add a custom message to override the default reminder text.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| ids | body | array of integer | Yes | Submission IDs to remind on. |
| customMessage | body | object | No | Notification subject and message. |
curl https://api.droplet.io/v1/submissions/remind \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "ids": [1042, 1043] }'
{
"requestId": "req_82cc",
"success": true,
"data": { "success": true }
}
Workflow actions
Send a submission back
POST /v1/submissions/send-back
Returns a submission to an earlier step, for example to request corrections. You must identify the step to send back to, a reason, and whether to reset the data captured since then.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| id | body | integer | Yes | The submission ID. |
| reason | body | string | Yes | Why the submission is being sent back. |
| stepId | body | string | Yes | The step to return to. |
| submittedAt | body | number | Yes | Timestamp of the target step submission. |
| resetData | body | boolean | Yes | Whether to clear data captured after the target step. |
curl https://api.droplet.io/v1/submissions/send-back \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"id": 1042,
"reason": "Missing start date",
"stepId": "applicant-info",
"submittedAt": 1746108130,
"resetData": false
}'
{
"requestId": "req_93dd",
"success": true,
"data": { "success": true, "message": "Submission sent back to Applicant Info" }
}
Set form version
POST /v1/submissions/set-form-version
Moves the listed submissions onto a specific form version. The response returns how many submissions were updated.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| ids | body | array of integer | Yes | Submission IDs to update. |
| version | body | string | Yes | The target form version. |
curl https://api.droplet.io/v1/submissions/set-form-version \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "ids": [1042, 1043], "version": "v4" }'
{
"requestId": "req_a4ee",
"success": true,
"data": { "count": 2 }
}
Set dataset version
POST /v1/submissions/set-dataset-version
Updates which dataset versions the listed submissions resolve against. Provide one entry per dataset you want to pin. The response returns how many submissions were updated.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| ids | body | array of integer | Yes | Submission IDs to update. |
| updatedVersions | body | array | Yes | Entries of { datasetId, versionId }. |
curl https://api.droplet.io/v1/submissions/set-dataset-version \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"ids": [1042],
"updatedVersions": [ { "datasetId": "locations", "versionId": 7 } ]
}'
{
"requestId": "req_b5ff",
"success": true,
"data": { "count": 1 }
}
Archiving and restoring
Archive submissions
POST /v1/submissions/archive
Archives the listed submissions, removing them from active views while keeping them recoverable. Returns the number archived.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| ids | body | array of integer | Yes | Submission IDs to archive. |
curl https://api.droplet.io/v1/submissions/archive \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "ids": [1042, 1043] }'
{
"requestId": "req_c601",
"success": true,
"data": { "count": 2 }
}
Restore submissions
POST /v1/submissions/restore
Restores previously archived submissions back into active status. Returns the number restored.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| ids | body | array of integer | Yes | Submission IDs to restore. |
curl https://api.droplet.io/v1/submissions/restore \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "ids": [1042] }'
{
"requestId": "req_d712",
"success": true,
"data": { "count": 1 }
}
Export, download, and PDF
The PDF and export endpoints return a serialized file payload in data plus a headers object describing the file (such as content type and disposition). Reconstruct the file on your side using those headers.
Generate a submission PDF
POST /v1/submissions/:id/pdf
Generates a PDF rendering of a single submission. Use options to tune layout and what to include, such as uploads, the activity log, or a data verification key.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| id | path | integer | Yes | The submission ID. |
| options | body | object | No | Booleans: compactLayout, reducedMargins, privateUploads, uploadsInPdf, generalInfo, dataVerificationKey, activityLog. All default to false. |
curl https://api.droplet.io/v1/submissions/1042/pdf \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "options": { "uploadsInPdf": true, "activityLog": true } }'
{
"requestId": "req_e823",
"success": true,
"data": {
"data": { "type": "Buffer", "data": [37, 80, 68, 70] },
"headers": {
"content-type": "application/pdf",
"content-disposition": "attachment; filename=\"submission-1042.pdf\""
}
}
}
Download submissions
POST /v1/submissions/download
Returns the listed submissions grouped by form, including each form's layout, steps, and datasets alongside its submissions. This is the structured download used to render or archive responses with full context.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| ids | body | array of integer | Yes | Submission IDs to download. |
curl https://api.droplet.io/v1/submissions/download \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "ids": [1042, 1043] }'
{
"requestId": "req_f934",
"success": true,
"data": {
"forms": [
{
"form": {
"id": "onboarding-2024",
"name": "New Hire Onboarding",
"version": "v3",
"layout": { /* ... */ },
"steps": { /* ... */ },
"datasets": { /* ... */ }
},
"submissions": [
{ "id": 1042, "status": "completed", "data": { "firstName": "Dana" } }
// ...
]
}
]
}
}
Get download settings
GET /v1/submissions/download/settings
Returns the form versions available for a given form so you can offer version choices before downloading.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| formId | query | string | Yes | The form to inspect. |
curl -G https://api.droplet.io/v1/submissions/download/settings \
-H "Authorization: Bearer <token>" \
--data-urlencode "formId=onboarding-2024"
{
"requestId": "req_0a45",
"success": true,
"data": {
"versions": [
{ "id": "onboarding-2024", "name": "New Hire Onboarding", "version": "v3" }
// ...
]
}
}
Get export settings
GET /v1/submissions/export/settings
Returns the available columns (headers) and repeating tables for a form, so you can build the column selection that the export endpoint expects.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| formId | query | string | Yes | The form to inspect. |
curl -G https://api.droplet.io/v1/submissions/export/settings \
-H "Authorization: Bearer <token>" \
--data-urlencode "formId=onboarding-2024"
{
"requestId": "req_1b56",
"success": true,
"data": {
"headers": [
{ "id": "firstName", "label": "First Name" },
{ "id": "startDate", "label": "Start Date" }
],
"tables": [
{
"id": "dependents",
"label": "Dependents",
"columns": [ { "id": "name", "label": "Name" } ]
}
]
}
}
Export submissions
POST /v1/submissions/export
Exports the chosen submissions as a spreadsheet file payload in CSV or XLSX. Use the export settings endpoint to discover valid header IDs, then pass them in options.headers.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| formId | body | string | Yes | The form being exported. |
| ids | body | array of integer | Yes | Submission IDs to export. |
| options | body | object | Yes | Export options (see below). |
| options.headers | body | array | Yes | Columns to include, each with an id and optional label. |
| options.format | body | string | Yes | csv or xlsx. |
| options.singleSheet | body | boolean | No | Combine output into one sheet. |
| options.inlineTables | body | boolean | No | Inline repeating-table data. |
| options.privateUploadLinks | body | boolean | No | Use private links for uploads. |
| options.tableId | body | string | No | Export a specific repeating table. |
curl https://api.droplet.io/v1/submissions/export \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"formId": "onboarding-2024",
"ids": [1042, 1043],
"options": {
"headers": [ { "id": "firstName" }, { "id": "startDate" } ],
"format": "xlsx"
}
}'
{
"requestId": "req_2c67",
"success": true,
"data": {
"data": { "type": "Buffer", "data": [80, 75, 3, 4] },
"headers": {
"content-type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"content-disposition": "attachment; filename=\"submissions.xlsx\""
}
}
}
Address helpers
Get address suggestions
GET /v1/submissions/address-suggestions
Returns address autocomplete suggestions for a partial address, ideal for powering address fields. Pass a stable sessionId to group related keystrokes.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| address | query | string | Yes | The partial address to complete. |
| sessionId | query | string | Yes | Autocomplete session identifier. |
curl -G https://api.droplet.io/v1/submissions/address-suggestions \
-H "Authorization: Bearer <token>" \
--data-urlencode "address=1600 Amphi" \
--data-urlencode "sessionId=sess_abc"
{
"requestId": "req_3d78",
"success": true,
"data": [
{
"placeId": "ChIJ2eUgeAK6j4ARbn5u_wAGqWA",
"mainText": "1600 Amphitheatre Parkway",
"secondaryText": "Mountain View, CA, USA"
}
]
}
Look up distance between addresses
POST /v1/submissions/distance-lookup
Calculates the distance between two addresses, useful for mileage or travel fields. The returned distance is a number you can format as needed.
| Parameter | In | Type | Required | Description |
|---|---|---|---|---|
| startAddress | body | string | Yes | The origin address. |
| endAddress | body | string | Yes | The destination address. |
curl https://api.droplet.io/v1/submissions/distance-lookup \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"startAddress": "1600 Amphitheatre Parkway, Mountain View, CA",
"endAddress": "1 Infinite Loop, Cupertino, CA"
}'
{
"requestId": "req_4e89",
"success": true,
"data": { "distance": 11.4 }
}
Every endpoint can also return an error envelope with success: false and an error object containing code and message. Check success before reading data.