Forms
Read-only access to forms and their responses. List forms, page through a form's responses, fetch a single response with its full comment context, or pull everything that changed since a timestamp — built for external dashboards, BI tools, and historical analysis.
Required scopes: read:forms for the form endpoints, read:formresponses for the response endpoints.
Endpoints
/api/open/v1/formsList forms (published by default, paginated)
/api/open/v1/forms/{id}Get a single form
/api/open/v1/forms/{id}/responsesList a form's responses (light payload, paginated)
/api/open/v1/formresponsesBulk feed of responses incl. form, comments and notes — ?since= for sync
/api/open/v1/formresponses/{id}Get a single response incl. form, comments and notes
List forms
curl "https://customer.monotree.com/api/open/v1/forms?status=published" \
-H "Authorization: Bearer mono_your_token_here"| Param | Notes |
|---|---|
status | published (default), draft, or all. |
since | Only forms created at or after this timestamp — ISO 8601, e.g. 2026-05-20T08:00:00Z (see timestamp format). |
per_page | Default 25, max 50. |
Form object
{
"data": {
"id": 12,
"title": "Maintenance Request",
"description": "Report broken equipment",
"instructions": "Fill out all fields",
"respondent_identity": "required",
"is_anonymous": false,
"is_commentable": true,
"allow_multiple_responses": true,
"is_published": true,
"published_at": "2026-05-01T08:00:00+00:00",
"due_at": "2026-06-01",
"groups": [
{ "id": 3, "name": "Kitchen Staff", "type": "department", "created_at": "2026-01-15T10:00:00+00:00" }
],
"responses_count": 118,
"created_at": "2026-04-28T09:00:00+00:00",
"updated_at": "2026-05-01T08:00:00+00:00"
}
}respondent_identity is required, optional, or anonymous; is_anonymous is true when identity is always anonymous. groups is the form's targeting — empty for a company-wide form. due_at is the date (YYYY-MM-DD) by which respondents should have answered — set per form in the CMS and shown in-app to users who have not yet responded; null when the form has no due date.
List a form's responses
A light payload — field responses without the comment threads. Use the single response or the bulk feed for full context.
curl "https://customer.monotree.com/api/open/v1/forms/12/responses?status=done" \
-H "Authorization: Bearer mono_your_token_here"| Param | Notes |
|---|---|
status | Workflow status: todo, in_progress, done, or null (no status). |
since | Only responses created at or after this timestamp — ISO 8601, e.g. 2026-05-20T08:00:00Z (see timestamp format). |
include_deleted | 1/true to also list deleted (archived) responses — their deleted_at is set. |
only_deleted | 1/true to list just the archive. See deleted responses. |
per_page | Default 25, max 100. |
{
"data": {
"id": 4521,
"form_id": 12,
"form_title": "Maintenance Request",
"form_due_at": "2026-06-01",
"is_anonymous": false,
"status": "done",
"respondent": { "id": 42, "name": "Jane Doe", "email": "jane@example.com" },
"assignees": [ { "id": 5, "name": "Sam Doe", "email": "sam@example.com" } ],
"department": { "id": 3, "name": "Kitchen Staff", "type": "department" },
"field_responses": [
{ "value": "Freezer 2 is above temperature", "field": { "id": 7, "title": "What happened?", "type": "text" } },
{ "value": [ { "id": 21, "title": "Urgent" } ], "field": { "id": 8, "title": "Priority", "type": "choices" } }
],
"media": [
{ "id": 55, "type": "image", "mime_type": "image/jpeg", "filename": "freezer.jpg", "size": 182034, "url": "https://…/freezer.jpg", "width": 1280, "height": 960, "created_at": "2026-05-20T07:45:00+00:00" }
],
"created_at": "2026-05-20T07:45:00+00:00",
"updated_at": "2026-05-20T09:10:00+00:00",
"deleted_at": null
}
}choices fields serialize their selections as { id, title } arrays; users and department_users fields as user objects. Hidden responses are never returned; deleted (archived) responses only when you opt in with include_deleted or only_deleted.
Every response object (light and detail) also carries form_due_at — the parent form's due date (null when the form has none) — assignees — the staff members currently assigned to handle the response (empty when unassigned) — and a deleted_at that is always present: null while the response exists, an ISO 8601 timestamp once it has been deleted.
Every response object (light and detail) includes media — the files uploaded with the submission. They belong to the response as a whole, not to a specific field. type is image, video or document, and url is a direct download link. On anonymous responses the files are stored encrypted, so url is a short-lived signed link (expires after ~5 minutes) — re-fetch the response whenever you need a fresh one.
Get a single response
Includes the embedded form, the shared public_comments thread, and the staff-only internal_comments — the full context for analysis. A deleted (archived) response returns 404 unless you pass ?include_deleted=1.
curl https://customer.monotree.com/api/open/v1/formresponses/4521 \
-H "Authorization: Bearer mono_your_token_here"{
"data": {
"id": 4521,
"form_id": 12,
"...": "…same fields as the list payload…",
"form": { "id": 12, "title": "Maintenance Request", "due_at": "2026-06-01", "...": "…full form object…" },
"public_comments": [
{
"id": 901,
"body": "Could you re-check the freezer reading?",
"form_response_id": 4521,
"form_id": 12,
"author": { "id": 5, "name": "Sam Doe", "email": "sam@example.com" },
"media": [
{ "id": 77, "type": "image", "mime_type": "image/jpeg", "filename": "freezer.jpg", "url": "https://cdn.monotree.dk/…/freezer.jpg", "width": 1200, "height": 800 }
],
"created_at": "2026-05-20T08:00:00+00:00",
"updated_at": "2026-05-20T08:00:00+00:00"
}
],
"internal_comments": [
{
"id": 33,
"body": "Escalated to facilities.",
"form_response_id": 4521,
"form_id": 12,
"author": { "id": 5, "name": "Sam Doe", "email": "sam@example.com" },
"created_at": "2026-05-20T08:05:00+00:00",
"updated_at": "2026-05-20T08:05:00+00:00"
}
]
}
}public_commentsis the thread shared with the respondent;authorisnullwhen the comment was written by the respondent on an anonymous response. Attachments arrive inmedia.internal_commentsare staff-only notes — never visible to the respondent in the app, exposed here for complete context.
Bulk feed with since
GET /formresponses returns the same detail payload as the single fetch, paginated across all forms — no need to iterate form ids. Its since parameter filters on updated_at, so one poll captures everything that happened since your last sync: new responses, field or workflow-status edits, and new public or internal comments (each bumps the response's updated_at). Results are ordered by updated_at descending.
curl "https://customer.monotree.com/api/open/v1/formresponses?since=2026-05-20T00:00:00Z" \
-H "Authorization: Bearer mono_your_token_here"| Param | Notes |
|---|---|
since | Responses created or updated at or after this timestamp — ISO 8601, e.g. 2026-05-20T08:00:00Z. Omit for a full dump (initial backfill). |
status | Workflow status: todo, in_progress, done, or null. |
include_deleted | 1/true to also include deleted (archived) responses — their deleted_at is set. Deleting bumps updated_at, so a since poll with this flag catches deletions your sync may have missed. |
only_deleted | 1/true to return just the archive. See deleted responses. |
per_page | Default 25, max 100. |
An invalid since or status returns 422. For push-based integration, the outgoing webhooks fire on response creation, updates, deletions, and comment activity.
Deleted (archived) responses
Responses deleted in the CMS are archived, not destroyed — they keep their id, field responses and comments, and gain a deleted_at timestamp. They are left out of every response endpoint by default; two flags opt in:
| Flag | Works on | Effect |
|---|---|---|
include_deleted=1 | all response endpoints | Deleted responses appear alongside live ones (deleted_at set); the single fetch returns the response instead of 404. |
only_deleted=1 | GET /forms/{id}/responses, GET /formresponses | Only deleted responses — the archive. Wins when both flags are sent. |
Whistleblower and hidden responses stay excluded regardless of these flags. Restoring a response in the CMS clears deleted_at again, so treat it as state rather than a tombstone.
# everything ever submitted to form 12 that has since been archived
curl "https://customer.monotree.com/api/open/v1/forms/12/responses?only_deleted=1" \
-H "Authorization: Bearer mono_your_token_here"The since timestamp format
Every since parameter on these endpoints takes an ISO 8601 timestamp. Always include the timezone — Z for UTC or an explicit offset:
?since=2026-05-20T08:00:00Z UTC
?since=2026-05-20T10:00:00%2B02:00 UTC+2 (a literal + must be url-encoded as %2B)
?since=2026-05-20 date only — midnight in the platform's timezoneValues without a timezone are interpreted in the platform's timezone, so send an explicit Z/offset to avoid surprises. Anything that can't be parsed as a date returns 422. When syncing, use the updated_at of the newest record you've already processed (the API returns timestamps in ISO 8601 with offset), and remember the comparison is inclusive (>=) — records exactly on the boundary appear again.