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

GET
/api/open/v1/forms

List forms (published by default, paginated)

GET
/api/open/v1/forms/{id}

Get a single form

GET
/api/open/v1/forms/{id}/responses

List a form's responses (light payload, paginated)

GET
/api/open/v1/formresponses

Bulk feed of responses incl. form, comments and notes — ?since= for sync

GET
/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"
ParamNotes
statuspublished (default), draft, or all.
sinceOnly forms created at or after this timestamp — ISO 8601, e.g. 2026-05-20T08:00:00Z (see timestamp format).
per_pageDefault 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"
ParamNotes
statusWorkflow status: todo, in_progress, done, or null (no status).
sinceOnly responses created at or after this timestamp — ISO 8601, e.g. 2026-05-20T08:00:00Z (see timestamp format).
include_deleted1/true to also list deleted (archived) responses — their deleted_at is set.
only_deleted1/true to list just the archive. See deleted responses.
per_pageDefault 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_comments is the thread shared with the respondent; author is null when the comment was written by the respondent on an anonymous response. Attachments arrive in media.
  • internal_comments are 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"
ParamNotes
sinceResponses created or updated at or after this timestamp — ISO 8601, e.g. 2026-05-20T08:00:00Z. Omit for a full dump (initial backfill).
statusWorkflow status: todo, in_progress, done, or null.
include_deleted1/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_deleted1/true to return just the archive. See deleted responses.
per_pageDefault 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:

FlagWorks onEffect
include_deleted=1all response endpointsDeleted responses appear alongside live ones (deleted_at set); the single fetch returns the response instead of 404.
only_deleted=1GET /forms/{id}/responses, GET /formresponsesOnly 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 timezone

Values 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.