New Format Coming Soon!

A new form format was released in April 2020. The V1 form format will continue to be available and used by older forms. Users will be able to continue to build and use V1 forms. No further changes or updates to the V1 format are expected.

Forms built with the new form builder will use the V2 data format. Details of the V2 format are still subject to change.

ProForma Data Format - V1

The JSON output of from an individual ProForma form (accessed via the proforma.forms.i1 property) will look like:

{
    "key": "proforma.forms.i1",
    "value": {
      "schemaVersion": 5,
      "id": 1,
      "projectFormId": 3,
      "submitted": true,
      "name": "Feature Request",
      "updated": "",
      "questions": [
        {
          "id": 1,
          "t": "h1",
          "q": "ProForma Feature Request"
        },
        {
          "id": 2,
          "t": "tl",
          "q": "Describe the desired feature",
          "v": {
            "rq": true
          },
          "jf": "summary",
          "text": "Example Desired Feature"
        },
        {
          "id": 3,
          "t": "pg",
          "q": "Can you give us an example use case explaining how you would use this feature?",
          "v": {},
          "jf": "description",
          "text": "Example description"
        },
        {
          "id": 4,
          "t": "in",
          "q": "Thanks for the suggestion",
          "v": {}
        }
      ],
      "formHash": "040cf7245c69d0ed7c8e13177c5cb05ac6cb3bec41355ce977b688df4579e303"
    }
  }
CODE

There are some points to remember when looking at the JSON output. 

  • The data schema version is stored in the '{{schemaVersion}}' property. 

  • Any form created with recent versions of ProForma should have the number 5 in this property. 

  • Questions are stored in order in the '{{questions}}' property. 

  • Each question has an ID in its '{{id}}' property which is unique within the form and does not change. All copies of the same form will share the same set of IDs. 

  • Each question has a type stored in its '{{t}}' property. See below for a list of the types. 

  • Text questions store their answer in the question '{{text}}' property. 

  • Date questions store their answer in the question '{{date}}' property. 

  • Time questions store their answer in the question '{{time}}' property. 

  • Choice questions store their answer in the choices listed on the question '{{choices}}' property. Choices which have been selected will have their property {{selected}} set to true. If the property {{selected}} is not present or is false then that choice is not selected. The question types are:

Question Types

This is how each question type is represented.

  • h1: section heading (read-only heading) 

  • in: information (read-only HTML) 

  • ts: short text 

  • tl: long text 

  • pg: paragraph text 

  • da: date 

  • dt: date and time 

  • ti: time 

  • cd: choice dropdown (select) 

  • cs: choice single (radio) 

  • cm: choice multiple (checkbox) 

  • no: number 

ProForma Data Format - v2

Format still subject to change

This format is still being finalised and is subject to change. Details are provided here for references purposes only.

{
  "$id": "https://thinktilt.com/proformaform.schema.json",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "ProForma form schema (draft)",
  "type": "object",
  "required": [
    "id",
    "updated",
    "design"
  ],
  "properties": {
    "id": {
      "description": "ID of this form in its context. A 'context' means a Jira issue or a Jira project or perhaps something else. IDs are not necessarily unique across all of ProForma, only unique within their context.",
      "type": "number"
    },
    "updated": {
      "description": "The date this form was last updated. Should be formatted as an ISO 8601 date and time in the UTC timezone (Z).",
      "format": "date-time",
      "type": "string"
    },
    "design": {
      "$ref": "#/definitions/design",
      "description": "The design of the form: the static parts that don't change when filled in such as questions, sections and layout."
    },
    "state": {
      "$ref": "#/definitions/state",
      "description": "The state of the form: the dynamic parts that people change when filling in a form. Optional property, it is not available on template forms."
    },
    "publish": {
      "$ref": "#/definitions/publishing",
      "description": "Optional property that configures how this form is published (if it is published somewhere). Used only on template forms, not available on forms."
    },
    "hash": {
      "description": "A hash of the critical parts of the form design used to detect if the form design has been changed without permission. Optional property, it is only populated if the form is connected to Jira fields.",
      "type": "string"
    }
  },
  "definitions": {
    "answer": {
      "description": "Answer to a single question on a form. Can also be used to define the default answer to a question.",
      "properties": {
        "choices": {
          "description": "IDs of choices that have been selected.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "date": {
          "description": "Date part of an answer.",
          "type": "string"
        },
        "text": {
          "description": "Text part of an answer.",
          "type": "string"
        },
        "time": {
          "description": "Time part of an answer.",
          "type": "string"
        },
        "users": {
          "description": "Users that have been selected.",
          "items": {
            "$ref": "#/definitions/user"
          },
          "type": "array"
        }
      },
      "type": "object"
    },
    "choice": {
      "description": "A choice on a choice question.",
      "properties": {
        "id": {
          "type": "string"
        },
        "label": {
          "type": "string"
        }
      },
      "type": "object"
    },
    "condition": {
      "description": "Base interface for a condition. Different types of conditions extend this to provide type-specific configuration of the condition.",
      "properties": {
        "conditionType": {
          "enum": [
            "hs"
          ],
          "type": "string"
        }
      },
      "type": "object"
    },
    "design": {
      "description": "The design of the form: the static parts that don't change when filled in such as questions, sections and layout.",
      "properties": {
        "conditions": {
          "description": "Conditions applied to sections, questions and choices which may change the visibility of those items.",
          "additionalProperties": {
            "$ref": "#/definitions/condition"
          },
          "type": "object"
        },
        "layout": {
          "$ref": "#/definitions/layout",
          "description": "Visual layout of the form, ie a document containing the structure and layout of where the sections and questions appear on the form. This is an ADF (Atlassian Document Format) document."
        },
        "questions": {
          "description": "Questions on the form.",
          "additionalProperties": {
            "$ref": "#/definitions/question"
          },
          "type": "object"
        },
        "sections": {
          "description": "Sections of the form, used to apply conditions to more of the form than just a single question. It is valid for a form to have zero sections; indeed it is normal when there are no conditions on the form.",
          "additionalProperties": {
            "$ref": "#/definitions/section"
          },
          "type": "object"
        },
        "settings": {
          "$ref": "#/definitions/settings",
          "description": "General form settings, ie those which affect the entire form. Other settings are applied at the section or question level."
        }
      },
      "type": "object"
    },
    "layout": {
      "description": "Visual layout of the form, ie a document containing the structure and layout of where the sections and questions appear on the form. This is an ADF (Atlassian Document Format) document.",
      "properties": {
        "version": {
          "enum": [
            1
          ],
          "type": "number"
        },
        "type": {
          "enum": [
            "doc"
          ],
          "type": "string"
        },
        "content": {
          "type": "array"
        }
      },
      "type": "object"
    },
    "publishing": {
      "description": "Configures how this form is published (if it is published somewhere). Used only on template forms, not available on forms.",
      "properties": {
        "jira": {
          "description": "Configures how this form is published within Jira. Used only on template forms, not available on forms.",
          "properties": {
            "issueRequestTypeIds": {
              "description": "The IDs of request types or issue types that this form is recommended for in the Jira issue view.",
              "items": {
                "type": "number"
              },
              "type": "array"
            },
            "newIssueIssueTypeIds": {
              "description": "The IDs of issue types that this form can create issues for. Forms with IDs populated here will be listed in the create issue form popup.",
              "items": {
                "type": "number"
              },
              "type": "array"
            },
            "newIssueRequestTypeIds": {
              "description": "The IDs of request types that this form can create issues for. Forms with IDs populated here will be listed in the create issue form popup.",
              "items": {
                "type": "number"
              },
              "type": "array"
            },
            "submitOnCreate": {
              "description": "Whether forms created by the create issue form feature should be submitted immediately. The default is true, which means the form will be submitted at the same time as the issue is created. If set to false the form will be not be submitted, instead it will be added to the issue with an open status.",
              "type": "boolean"
            }
          },
          "type": "object"
        },
        "portal": {
          "description": "Configures how this form is published on the Jira Service Desk portal. Used only on template forms, not available on forms.",
          "properties": {
            "portalRequestTypeIds": {
              "description": "The IDs of request types that this form will appear on in the JSD portal. Forms with IDs populated here will be listed on the JSD portal.",
              "items": {
                "type": "number"
              },
              "type": "array"
            },
            "submitOnCreate": {
              "description": "Whether forms created by the JSD portal should be submitted immediately. The default is true, which means the form will be submitted immediately after the portal request is created. If set to false the form will be not be submitted, instead it will be added to the request with an open status.",
              "type": "boolean"
            }
          },
          "type": "object"
        }
      },
      "type": "object"
    },
    "question": {
      "description": "A single question on a form.",
      "properties": {
        "choices": {
          "description": "Choices defined for this question. Only applicable to choice questions. If a choice question is linked to a Jira field then the choices will be populated from the Jira field and should not be saved in the form itself while the form is open.",
          "items": {
            "$ref": "#/definitions/choice"
          },
          "type": "array"
        },
        "conditions": {
          "description": "Conditions applicable to this question.",
          "items": {
            "type": "string"
          },
          "type": "array"
        },
        "dcId": {
          "description": "The linked data connection id, if any. When linked to a data connection, the available answers are sourced from the data connection and the answer IDs are stored in the form directly.",
          "type": "string"
        },
        "default": {
          "$ref": "#/definitions/answer",
          "description": "The default value for this question, if any. If populated then this answer is automatically applied when the form is filled in."
        },
        "description": {
          "description": "An optional description displayed to people filling out the form. Intended for help text or other information associated directly with the question.",
          "type": "string"
        },
        "jiraField": {
          "description": "The linked Jira field, if any. When linked to a Jira field the answer to a question is stored on the Jira field for the issue rather than in the form directly — while the form is open, it is saved in the form on submit.",
          "type": "string"
        },
        "label": {
          "description": "The label displayed to people filling out the form. Though it is required, it may be an empty string.",
          "type": "string"
        },
        "type": {
          "description": "Type of question: defines how the question appears and is used on the form, and how it can be answered.",
          "enum": [
            "cd",
            "cm",
            "cs",
            "da",
            "dt",
            "no",
            "pg",
            "te",
            "ti",
            "tl",
            "ts",
            "tu",
            "um",
            "us"
          ],
          "type": "string"
        },
        "validation": {
          "description": "Validation rules for the question. It is valid for this to contain no validation rules. Certain types have implied validation rules which are not explicitly added to `validation`; for example email questions validate that an answer is a valid email address but do not have store a specific validator in the form template.",
          "properties": {
            "ch": {
              "description": "ID of required choice",
              "type": "number"
            },
            "mnc": {
              "description": "Minimum characters",
              "type": "number"
            },
            "mnd": {
              "description": "Minimum date",
              "type": "string"
            },
            "mnn": {
              "description": "Minimum number",
              "type": "number"
            },
            "mns": {
              "description": "Minimum number of choice selections",
              "type": "number"
            },
            "mnt": {
              "description": "Minimum time",
              "type": "string"
            },
            "mnw": {
              "description": "Minimum words",
              "type": "number"
            },
            "mxc": {
              "description": "Maximum characters",
              "type": "number"
            },
            "mxd": {
              "description": "Maximum date",
              "type": "string"
            },
            "mxn": {
              "description": "Maximum number",
              "type": "number"
            },
            "mxs": {
              "description": "Maximum number of choice selections",
              "type": "number"
            },
            "mxt": {
              "description": "Maximum time",
              "type": "string"
            },
            "mxw": {
              "description": "Maximum words",
              "type": "number"
            },
            "rgx": {
              "description": "Regex format validation",
              "properties": {
                "m": {
                  "description": "Message to display to user if the answer doesn't match the expected format",
                  "type": "string"
                },
                "p": {
                  "description": "Regex pattern",
                  "type": "string"
                }
              },
              "type": "object"
            },
            "rq": {
              "description": "Required",
              "type": "boolean"
            },
            "wh": {
              "description": "Whole numbers only",
              "type": "boolean"
            }
          },
          "type": "object"
        }
      },
      "type": "object"
    },
    "section": {
      "description": "A single section of a form.",
      "properties": {
        "sectionType": {
          "description": "The type of this section. Set to `Block` by default.",
          "enum": [
            "b",
            "p"
          ],
          "type": "string"
        }
      },
      "type": "object"
    },
    "settings": {
      "description": "General form settings, ie those which affect the entire form. Other settings are applied at the section or question level.",
      "properties": {
        "language": {
          "description": "Optional language of this form. The language set here defines what language to use for the UI on the form such as buttons and validation messages. It does not affect the text of the questions or answers which could be written by users in any language (or even none!)  If not provided then the language will be determined automatically based on the user's language settings.",
          "type": "string"
        },
        "name": {
          "description": "The name of this form, set by the form designer.",
          "type": "string"
        },
        "submit": {
          "description": "Settings controlling what happens on submit of this form.",
          "properties": {
            "lock": {
              "description": "Whether to lock the form when it is submitted. The default is false, meaning the form is submitted but it can be reopened later. If set to true the form is locked when submitted, meaning it cannot be reopened later (unless overridden by an administrator).",
              "type": "boolean"
            },
            "pdf": {
              "description": "Whether to generate a PDF of the form when it is submitted. The default is false, meaning no PDF is generated by default.",
              "type": "boolean"
            }
          },
          "type": "object"
        },
        "templateId": {
          "description": "The ID of the template form that this form was created from. When this form is itself a template form `templateId` should be equal to the `id` of the form.",
          "type": "number"
        }
      },
      "type": "object"
    },
    "state": {
      "description": "The state of the form: the dynamic parts that people change when filling in a form. Optional property, it is not available on template forms.",
      "properties": {
        "answers": {
          "description": "The answers to questions on this form. Answers will only be populated when someone fills out a form; if the form has not been filled out then the answers object may be empty. It is also possible for the answers object to be partially populated: some but not all answers listed. However there should not a situation where there is an answer which does not have a matching question in the form questions object.",
          "additionalProperties": {
            "$ref": "#/definitions/answer"
          },
          "type": "object"
        },
        "status": {
          "description": "The status of a form: open, submitted or locked.",
          "enum": [
            "l",
            "o",
            "s"
          ],
          "type": "string"
        },
        "visibility": {
          "description": "The visibility of a form, which may be internal or external. This only has meaning in the context of a form on Jira Service Desk. Its meaning in other contexts is undefined. Forms should default to using Internal in other contexts because Internal is more restrictive and so probably a safer choice should a form ever be moved into Jira Service Desk.",
          "enum": [
            "e",
            "i"
          ],
          "type": "string"
        }
      },
      "type": "object"
    },
    "user": {
      "description": "A user selected in a user picker.",
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        }
      },
      "type": "object"
    }
  }
}
JSON